4

I am quite new to this whole threading thing, so hopefully someone can enlighten me.

I have a WPF UI from which I start a DLL on the click of a button. When the button is clicked, it runs the dll asynchronously so that the user can still "navigate" the UI while the dll is performing its work:

await Task.Factory.StartNew(new Action(() => strTime = 
                                             StartSync.Start(strPathFile,
                                             licManager.idCmsMediator)));

this worked very well until I had to run this Task on STA mode to open windows in the dll. So I changed this line using the method described in this post :

var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
await Task.Factory.StartNew(new Action(() => strTime = 
                                             StartSync.Start(strPathFile,
                                             licManager.idCmsMediator)),
                                             System.Threading.CancellationToken.None, 
                                             TaskCreationOptions.None, scheduler);

but now when I run the dll by clicking the button, I cannot navigate the UI anymore ! Like it is NOT running asynchronously anymore !? How can I start the task in STA mode but still be able to navigate the UI ?

Thanks in advance

Community
  • 1
  • 1
Julien
  • 263
  • 2
  • 9
  • 3
    You have mutually contradictory requirements - you want to run this job on the background thread but at the same time, you're also saying that it has to run on the UI thread. You cannot have both. – Damien_The_Unbeliever May 21 '15 at 07:52
  • I think you are waiting for the Async task to complete when you add the await in front of the Task factory.. – Johan May 21 '15 at 07:54
  • If you want to show a window, show it in UI thread. Don't mix UI and worker thread. Otherwise, you'll regret. – Sriram Sakthivel May 21 '15 at 07:59
  • There will not be any regret, any access of UI component via worker thread will be direct exception :). .Net just doesn't allow it. UI components only on UI thread – Mrinal Kamboj May 21 '15 at 08:34

1 Answers1

3

but now when I run the dll by clicking the button, I cannot navigate the UI

Task != Thread. A task may or may not use a thread to do it's work. When you use:

var scheduler = TaskScheduler.FromCurrentSynchronizationContext();

You're telling the task factory to execute the given delegate on the current captured synchronization context, which is your UI synchronization context. When you do that, it will execute this on the UI message loop.

this worked very well until I had to run this Task on STA mode to open windows in the dll

Opening a window should be done on the UI thread, hence why it's complaining. What you can do is defer the execution of the CPU bound work the a background thread, and once you need to manipulate the UI, marshal the work back:

// Start CPU bound work on a background thread
await Task.Run(() => strTime = StartSync.DoCpuWork(strPathFile, 
                                                   licManager.idCmsMediator)));

// We're done awaiting, back onto the UI thread, Update window.
Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
  • @Julien If you want to use a `Task`, and need to it be STA, you can use the code I've provided. If you want to simply manipulate the UI and this has nothing to do with STA, you'll need to execute it on the UI thread. – Yuval Itzchakov May 21 '15 at 07:56
  • I eventually got it working with a bit of fiddling around using your solution, thanks ! – Julien May 21 '15 at 08:11
  • Why is the synchronization set to current / UI threads here, is the call updating the UI control somewhere, which needs only UI thread. @Yuval Itzchakov I guess you solution have just taken processing async, there's no STA involved, I am not sure why OP has mentioned STA – Mrinal Kamboj May 21 '15 at 08:37