www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Appending Text to SWT Textbox from multiple threads.

reply "Sharad Gupta" <gsharad007 yahoo.com> writes:
Hi All,

I am trying to update a text box from another thread but it has 
me stumped right now.

What I am trying to achieve is that the user can Initiate 
multiple pipeShell and the output from each of those should go 
into its own Textbox in parallel.

I tried creating the SWT UI Controls inside as well as outside my 
spawn but since they get added to a single parent Control its 
getting maddeningly frustrating.

Here is the Code:

     int nextIndex = 1;
     Text[int] statusItems;

     public int addStatus(string title, string process = "", int 
waitFor = 0)
     {
         int idx = nextIndex;
         nextIndex++;
         Tid id = spawn(&addStatusImpl, idx, title, process, 
waitFor);

// tabStatuses = new TabFolder(canvas,SWT.TOP);
         auto statusItem = new Text(tabStatuses);
         auto tabItem = new TabItem(tabStatuses, SWT.NONE);
         send(id, statusItem, tabItem);

         std.concurrency.register(title, id);

         //auto msg = receiveOnly!(int, Text)();
         //statusItems[idx] = msg[1];
         //return msg[0];
         return idx;
     }

     static private void addStatusImpl(int idx, string title, 
string process = "", int waitFor = 0)
     {
         auto msg = receiveOnly!(Text, TabItem)();
         Text item = msg[0];

         //send(idx, item);

         TabItem tabItem = msg[1];
         tabItem.setText(title);
         tabItem.setControl(item);

         if(process.length != 0)
         {
             Text b = statusItems.get(waitFor, null);
             Tid id;
             if(b is null)
                 addProcess(item, process, null, null);
             else
                 addProcess(item, process, b.processPipe.pid(), 
b.title);
         }
     }

static public void addProcess(Text txtStatus, string command, Pid 
waitFor, string waitForTitle)
{
     if(waitFor !is null)
     {
         auto blocker = tryWait(waitFor);
         if(!blocker.terminated)
         {
             txtStatus.append("Waiting for " ~ waitForTitle ~ 
"...\n");
             wait(waitFor);
         }
         if(blocker.status != 0)
         {
             txtStatus.append("ERROR: Process " ~ waitForTitle ~ " 
did not finish properly. Terminating Self.\n");
             return;
         }
     }

     string finalCommand = escapeShellCommand(command);
     auto pipes = pipeShell(finalCommand, Redirect.all, null, 
std.process.Config.suppressConsole);
     scope(exit) wait(pipes.pid);

     foreach(str; pipes.stdout.byLine)
     {
         string s = to!string(str);
         txtStatus.append(s);
     }

     foreach(str; pipes.stderr.byLine)
     {
         string s = to!string(str);
         txtStatus.append(s);
     }
}

Can someone please help me with a solution. I am new to D (long 
term c/c++ programmer) and am probably missing something.

Also any tips to do stuff the "D" way would also be appreciated 
as you can see that my mind set is still C-style coding.

Thank you all.
Mar 17 2014
parent reply "Jacob Carlborg" <doob me.com> writes:
On Monday, 17 March 2014 at 23:16:16 UTC, Sharad Gupta wrote:
 Hi All,

 I am trying to update a text box from another thread but it has 
 me stumped right now.

 What I am trying to achieve is that the user can Initiate 
 multiple pipeShell and the output from each of those should go 
 into its own Textbox in parallel.

 I tried creating the SWT UI Controls inside as well as outside 
 my spawn but since they get added to a single parent Control 
 its getting maddeningly frustrating.
What exact problems do you have? Note that SWT is not thread safe. All UI changes need to be made on the UI thread. This is usually done using the "Display.asyncExec" method. -- /Jacob Carlborg
Mar 18 2014
parent reply "Jacob Carlborg" <doob me.com> writes:
On Tuesday, 18 March 2014 at 07:19:05 UTC, Jacob Carlborg wrote:

 What exact problems do you have?

 Note that SWT is not thread safe. All UI changes need to be 
 made on the UI thread. This is usually done using the 
 "Display.asyncExec" method.
Forgot the link to the example: http://git.eclipse.org/c/platform/eclipse.platform.swt.git/tree/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet56.java -- /Jacob Carlborg
Mar 18 2014
parent "Sharad Gupta" <gsharad007 yahoo.com> writes:
On Tuesday, 18 March 2014 at 07:20:05 UTC, Jacob Carlborg wrote:
 On Tuesday, 18 March 2014 at 07:19:05 UTC, Jacob Carlborg wrote:

 What exact problems do you have?

 Note that SWT is not thread safe. All UI changes need to be 
 made on the UI thread. This is usually done using the 
 "Display.asyncExec" method.
Forgot the link to the example: http://git.eclipse.org/c/platform/eclipse.platform.swt.git/tree/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet56.java -- /Jacob Carlborg
Yeah I have seen that but haven't tried it on the account that I'll have the same problem as before where I cannot pass Display to the spawned Process. I think if I used core.Thread I would be able to do this easily but I wanted to first investigate a possible solution with std.concurrency.spawn and its additional checks. Maybe D needs a way to mark an object as Thread-Local and bypass some of these checks.
Mar 18 2014