BackgroundWorker Using a COM Object Results in UI Thread Hangup - c#

I have a dedicated class that includes a BackgroundWorker that is responsible for running class-specific actions from a queue - actions which require use of a COM object.
Objects the dedicated class are created during runtime from the UI thread when the application starts up (WPF). When the class' constructor is called, it instantiates a BackgroundWorker that runs asynchronously dequeuing Actions assigned from the UI thread.
However, when these Actions require data resulting from the COM object, I notice that the UI thread is waiting on the BackgroundWorker to finish the Action before reacting to user input.
How can I isolate so that the UI thread is not impacted by the COM's functions that can take up to 10 seconds to complete?
Code:
public class User(){
private BackgroundWorker Worker;
private Queue<Action> ActionQueue;
private COM COMObject; // COM is an interface exposed by the COM referenced in VS project
private bool Registered;
public User(){
this.Registered = true;
this.ActionQueue = new Queue<Action>();
this.Worker = new BackgroundWorker();
this.Worker.DoWork += new DoWorkEventHandler(DoWork);
this.Worker.DoWork += new RunWorkerCompletedEventHandler(WorkerCompleted);
this.Worker.Worker.WorkerSupportsCancellation = true;
this.Worker.Worker.RunWorkerAsync();
this.COMObject = new COM();
}
private DoWork(object sender, DoWorkEventArgs e){
// If there is something to be done (an action) in the queue
if (ActionQueue.Count > 0){
// Dequeue the action from the queue
Action queuedAction = ActionQueue.Dequeue();
// Do the action
queuedAction();
}
}
private void WorkerCompleted(object sender, RunWorkerCompletedEventArgs e){
// While this machine continues to be registered to the app...
if (this.Registered)
{
Worker.RunWorkerAsync();
}
}
public void ConnectToDatabase(){
Action action = delegate {
COMObject.Connect(); // function can take up to 10 seconds to return
}; // end of action delegate
ActionQueue.Enqueue(action);
}
}
Use Code (in UI thread):
User user = new User();
user.ConnectToDatabase();
In my UI, during application startup, there can be up to 10 User objects created and called to connect. If I comment out the COMObject.Connect(); line in User::ConnectToDatabase and replace with Thread.Sleep(10000) the UI thread does not wait 10+ seconds. But, as is the code now, I notice that the COMObject.Connect(); line does result in 10+ seconds before any user input in the WPF app is processed again.
How can I isolate so that the functions related to the COM object do not impact the performance of the UI thread?
(Note: there is no interaction with the UI thread from the actions queued with the BackgroundWorker. Only class-specific properties are changed in those actions).

The answers always lurk in the comments :)
As #Blindy and #jdweng pointed out, the new COM() was being called on the main UI thread, whereas all the functionality of the COM object was being used on a different thread.
In addition, I did set the COM object's thread with the STAThread attribute (this.Worker.SetApartmentState(ApartmentState.STA);).
And, I did change from using a BackgroundWorker to an actual Thread.
And, last, but not least, as #Blindy called out the issue with using a Queue<Action> to do work on the Worker thread, queued from the main UI thread, I did end up using a ConcurrentQueue<Action>, per #Anders H's suggestion. I would have used Tasks, which from the amount of research I did on the topic would have solved the cross-thread access potential issue, but, because queued "work" would have to be done sequentially and relating to the COM object, the ConcurrentQueue ended up seeming like a decent solution for the time being. But, will have to revisit this later on.

Related

C# Firing events within the thread they are added

Consider two classes; Producer and Consumer (the same as classical pattern, each with their own threads). Is it possible for Producer to have an Event which Consumer can register to and when the producer triggers the event, the consumer's event handler is run in its own thread? Here are my assumptions:
Consumer does not know if the Producer's event is triggered
within his own thread or another.
Neither Producer nor Consumer are descendants of Control so they don't have
BeginInvoke method inherited.
PS. I'm not trying to implement Producer - Consumer pattern. These are two simple classes which I'm trying to refactor the producer so it incorporates threads.
[UPDATE]
To further expand my problem, I'm trying to wrap a hardware driver to be worked with in the simplest way possible. For instance my wrapper will have a StateChanged event which the main application will register to so it will be notified when hardware is disconnected. As the actual driver has no means other than polling to check its presence , I will need to start a thread to check it periodically. Once it is not available anymore I will trigger the event which needs to be executed in the same thread as it was added. I know this is a classical Producer-Consumer pattern but since I'm trying to simplify using my driver-wrapper, I don't want the user code to implement consumer.
[UPDATE]
Due to some comments suggesting that there's no solution to this problem, I would like to add few lines which might change their minds. Considering the BeginInvoke can do what I want, so it shouldn't be impossible (at least in theory). Implementing my own BeginInvoke and calling it within the Producer is one way to look at it. It's just that I don't know how BeginInvoke does it!
You want to do inter thread communication. Yes it is possible.
Use System.Windows.Threading.Dispatcher
http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.aspx
The Dispatcher maintains a prioritized queue of work items for a specific thread.
When a Dispatcher is created on a thread, it becomes the only Dispatcher that can be associated with the thread, even if the Dispatcher is shut down.
If you attempt to get the CurrentDispatcher for the current thread and a Dispatcher is not associated with the thread, a Dispatcher will be created. A Dispatcher is also created when you create a DispatcherObject. If you create a Dispatcher on a background thread, be sure to shut down the dispatcher before exiting the thread.
Yes there is a way to do this. It relies on using the SynchronizationContext class (docs). The sync context abstracts the operations of sending messages from one thread to another via the methods Send (synchronous for the calling thread) and Post(async for the calling thread).
Let's take a slightly simpler situation where you only want the capture one sync context, the context of the "creator" thread. You would do something like this:
using System.Threading;
class HardwareEvents
{
private SynchronizationContext context;
private Timer timer;
public HardwareEvents()
{
context = SynchronizationContext.Current ?? new SynchronizationContext();
timer = new Timer(TimerMethod, null, 0, 1000); // start immediately, 1 sec interval.
}
private void TimerMethod(object state)
{
bool hardwareStateChanged = GetHardwareState();
if (hardwareStateChanged)
context.Post(s => StateChanged(this, EventArgs.Empty), null);
}
public event EventHandler StateChanged;
private bool GetHardwareState()
{
// do something to get the state here.
return true;
}
}
Now, the creating thread's sync context will be used when events are invoked. If the creating thread was a UI thread it will have a sync context supplied by the framework. If there is no sync context, then the default implementation is used, which invokes on the thread pool. SynchronizationContext is a class that you can subclass if you want to provide a custom way to send a message from the producer to the consumer thread. Just override Post and Send to send said message.
If you wanted every event subscriber to get called back on their own thread, you would have to capture the sync context in the add method. You then hold on to pairs of sync contexts and delegates. Then when raising the event, you would loop through the sync context / delegate pairs and Post each one in turn.
There are several other ways you could improve this. For example, you may want to suspend polling the hardware if there no subscribers to the event. Or you might want to back off your polling frequency if the hardware does not respond.
First, please note that in .NET / the Base Class Library, it is usually the event subscriber's obligation to ensure that its callback code is executing on the correct thread. That makes it easy for the event producer: it may just trigger its event without having to care about any thread affinities of its various subscribers.
Here's a complete example step-by-step of a possible implementation.
Let's start with something simple: The Producer class and its event, Event. My example won't include how and when this event gets triggered:
class Producer
{
public event EventHandler Event; // raised e.g. with `Event(this, EventArgs.Empty);`
}
Next, we want to be able to subscribe our Consumer instances to this event and be called back on a specific thread (I'll call this kind of thread a "worker thread"):
class Consumer
{
public void SubscribeToEventOf(Producer producer, WorkerThread targetWorkerThread) {…}
}
How do we implement this?
First, we need the means to "send" code to a specific worker thread. Since there is no way to force a thread to execute a particular method whenever you want it to, you must arrange for a worker thread to explicitly wait for work items. One way to do this is via a work item queue. Here's a possible implementation for WorkerThread:
sealed class WorkerThread
{
public WorkerThread()
{
this.workItems = new Queue<Action>();
this.workItemAvailable = new AutoResetEvent(initialState: false);
new Thread(ProcessWorkItems) { IsBackground = true }.Start();
}
readonly Queue<Action> workItems;
readonly AutoResetEvent workItemAvailable;
public void QueueWorkItem(Action workItem)
{
lock (workItems) // this is not extensively tested btw.
{
workItems.Enqueue(workItem);
}
workItemAvailable.Set();
}
void ProcessWorkItems()
{
for (;;)
{
workItemAvailable.WaitOne();
Action workItem;
lock (workItems) // dito, not extensively tested.
{
workItem = workItems.Dequeue();
if (workItems.Count > 0) workItemAvailable.Set();
}
workItem.Invoke();
}
}
}
This class basically starts a thread, and puts it in an infinite loop that falls asleep (WaitOne) until an item arrives in its queue (workItems). Once that happens, the item — an Action — is dequeued and invoked. Then the thread goes to sleep again (WaitOne)) until another item is available in the queue.
Actions are put in the queue via the QueueWorkItem method. So essentially we can now send code to be executed to a specific WorkerThread instance by calling that method. We're now ready to implement Customer.SubscribeToEventOf:
class Consumer
{
public void SubscribeToEventOf(Producer producer, WorkerThread targetWorkerThread)
{
producer.Event += delegate(object sender, EventArgs e)
{
targetWorkerThread.QueueWorkItem(() => OnEvent(sender, e));
};
}
protected virtual void OnEvent(object sender, EventArgs e)
{
// this code is executed on the worker thread(s) passed to `Subscribe…`.
}
}
Voilà!
P.S. (not discussed in detail): As an add-on, you could package the method of sending code to WorkerThread using a standard .NET mechanism called a SynchronizationContext:
sealed class WorkerThreadSynchronizationContext : SynchronizationContext
{
public WorkerThreadSynchronizationContext(WorkerThread workerThread)
{
this.workerThread = workerThread;
}
private readonly WorkerThread workerThread;
public override void Post(SendOrPostCallback d, object state)
{
workerThread.QueueWorkItem(() => d(state));
}
// other overrides for `Send` etc. omitted
}
And at the beginning of WorkerThread.ProcessWorkItems, you'd set the synchronization context for that particular thread as follows:
SynchronizationContext.SetSynchronizationContext(
new WorkerThreadSynchronizationContext(this));
I posted earlier that I've been there, and that there is no nice solution.
However, I just stumbled upon something I have done in another context before: you could instantiate a timer (that is, Windows.Forms.Timer) when you create your wrapper object. This timer will post all Tick events to the ui thread.
Now if you're device polling logic is non-blocking and fast, you could implement it directly inside the timer Tick event, and raise your custom event there.
Otherwise, you could continue to do the polling logic inside a thread, and instead of firing the event inside the thread, you just flip some boolean variable which gets read by the timer every 10 ms, who then fires the event.
Note that this solution still requires that the object is created from the GUI thread, but at least the user of the object will not have to worry about Invoke.
It is possible. One typical approach is to use the BlockingCollection class. This data structure works like a normal queue except that the dequeue operation blocks the calling thread if the queue is empty. The produce will queue items by calling Add and the consumer will dequeue them by calling Take. The consumer typically runs it's own dedicated thread spinning an infinite loop waiting for items to appear in the queue. This is, more or less, how the message loop on the UI thread operates and is the basis for getting the Invoke and BeginInvoke operations to accomplish the marshaling behavior.
public class Consumer
{
private BlockingCollection<Action> queue = new BlockingCollection<Action>();
public Consumer()
{
var thread = new Thread(
() =>
{
while (true)
{
Action method = queue.Take();
method();
}
});
thread.Start();
}
public void BeginInvoke(Action method)
{
queue.Add(item);
}
}

Windows Client GUI Design Advice - Accessing UI Thread from Long Running Task

Web Developer here and need some advice on how to achieve what must be a common requirement in Windows Forms.
I have a windows client app that calls a business object in a separate project to perform some long running tasks. Difference to other examples is that the process live in another class library i.e. Business.LongRunningTask();
I have a list box in the client that I would like to have logged to by the task. I can run the process on the UI thread passsing in the instance of the textbox and calling Application.DoEvents() when I log to the textbox from within the task. All fine, but not elegant and would prefer not to call Application.DoEvents();
If I run the long running process on a separate thread using delegates I cannot access the textbox or delegates created in the windows client form which rules out BeginInvoke calls.
Surely this is bad design on my part and would appreciate some feedback.
You're looking for the BackgroundWorker class.
To execute a time-consuming operation in the background, create a BackgroundWorker and listen for events that report the progress of your operation and signal when your operation is finished.
You can find a complete example here: http://msdn.microsoft.com/en-us/library/b2zk6580(v=VS.100).aspx#Y1351
I can run the process on the UI thread
passsing in the instance of the
textbox and calling
Application.DoEvents() when I log to
the textbox from within the task.
Yes, you could also pass in an instance of ILoggingINnterface that you have used to put in the code to write to the text box FROM WITHIN THE UI and thus have taken care of all the nice BginInvoke stuff ;)
If I run the long running process on a
separate thread using delegates I
cannot access the textbox or delegates
created in the windows client form
which rules out BeginInvoke calls.
Ah. No. You just most invoke back to the dispatcher thread then you can access all the UI elemente you like.
Yeah, avoid Application.DoEvents().
To marshall the call back onto the UI thread, call this.Invoke(YourDelegate)
To access UI elements from a different thread, you can use control.Invoke to call a delegate on the owning thread.
I used this at one point to create a live log screen which was updated from a timer while a different worker thread was running. Heres a simplified version:
public class DifferentClassLibrary
{
public delegate void StringDataDelegate(string data);
public event StringDataDelegate UpdatedData;
public void DoStuff()
{
if (UpdatedData != null)
{
Thread.Sleep(10000);
UpdatedData("data");
}
}
}
And in the winform:
public void UpdateTextBoxCallback(string data)
{
if (uiTextBoxLiveLogView.InvokeRequired)
{
uiTextBoxLiveLogView.Invoke(new DifferentClassLibrary.StringDataDelegate(UpdateTextBoxCallback), data);
}
else
{
uiTextBoxLiveLogView.Text += data;
}
}
void Main()
{
DifferentClassLibrary test = new DifferentClassLibrary();
test.UpdatedData += UpdateTextBoxCallback;
Thread thread = new Thread(new ThreadStart(test.DoStuff));
thread.Start();
}

Need help with threading -C# Windows Forms

I am trying to create a thread that contains a form progress bar (just a GIF image).
I have called StartProgress() right before a large method. Basically when the thread starts it loads up the ProgressBar form (which I want to show all the time, and just hide it when it's not needed) and with ProgressActive set to true, it should display the form until ProgressActive is false, then the form should be hidden (until progress is active again). Here is what I have so far, but it freezes up on me :(
public static string ProgressInfo="Test";
public static bool ProgressActive=true;
public static bool ThreadStarted = false;
public static void StartProgress()
{
while (!ThreadStarted)
{
Thread t = new Thread(new ThreadStart(Progress));
ThreadStarted = true;
t.Start();
}
}
public static void Progress()
{
while (ThreadStarted)
{
LoadingBar lb = new LoadingBar();
lb.Show();
lb.TopMost = true;
while (ThreadStarted)
{
if (ProgressActive)
{
lb.Visible = true;
lb.lblLoadingStatus.Text = ProgressInfo;
}
else
{
lb.Visible = false;
}
Thread.Sleep(1000);
}
}
}
EDIT: I am trying to do this within a static class.
Is there any reason for not using BackgroundWorker if using .NET 2.0 or higher?
The reason I am saying that is because BackgroundWorker is event based, so it exposes an event like ProgressChanged which can reduce the overall size of your code.
The freezing is due to the fact you are trying to change your progress bar contained on the UI thread from your worker thread. I would recommend raising an event from within your worker Progress function to a handler on the UI thread. You will need to marshall the call to the handler on the thread as below.
private object _lock = new object(); //should have class scope
private void ShowProgressControl(EventArgs e)
{
if (this.InvokeRequired)
{
lock (_lock)
{
EventHandler d = new EventHandler(ShowProgressControl);
this.Invoke(d, new object[] { e });
return;
}
}
else
{
//Show your progress bar.
}
}
Enjoy!
The problem is that you need a message loop for any UI element to work correctly. Since you are creating the form in a worker thread then there is no message loop running. To create the message loop you have to call Application.Run or Form.ShowDialog both of which are blocking calls. Obviously that solution would hang up your worker thread.
The best thing to do is to create a separate thread dedicated to running the message loop and which can safely handle forms and controls. Have the worker thread periodically publish progress information to a variable that can be shared between the worker thread and the UI thread. Then have the UI thread periodically poll (using System.Windows.Form.Timer) that shared variable and update the UI accordingly.
As a side note, I would avoid using Control.Invoke or Control.BeginInvoke to push the progress information to the UI thread. You situation seems to warrant the polling approach instead. The reasons for preferring polling over pushing are:
It breaks the tight coupling between the UI and worker threads that Control.Invoke imposes.
It puts the responsibility of updating the UI thread on the UI thread where it should belong anyway.
The UI thread gets to dictate when and how often the update should take place.
There is no risk of the UI message pump being overrun as would be the case with the marshaling techniques initiated by the worker thread.
The worker thread does not have to wait for an acknowledgement that the update was performed before proceeding with its next steps (ie. you get more throughput on both the UI and worker threads).
You should create the progress bar on the main thread.
Make sure your heavy procedure runs from another thread.

synchronize threads - no UI

I'm trying to write multithreading code and facing some synchronization questions. I know there are lots of posts here but I couldn't find anything that fits.
I have a System.Timers.Timer that elapsed every 30 seconds it goes to the db and checks if there are any new jobs. If he finds one, he executes the job on the current thread (timer open new thread for every elapsed). While the job is running I need to notify the main thread (where the timer is) about the progress.
Notes:
I don't have UI so I can't do beginInvoke (or use background thread) as I usually do in winforms.
I thought to implement ISynchronizeInvoke on my main class but that looks a little bit overkill (maybe I'm wrong here).
I have an event in my job class and the main class register to it and I invoke the event whenever I need but I'm worrying it might cause blocking.
Each job can take up to 20 minutes.
I can have up to 20 jobs running concurrently.
My question is:
What is the right way to notify my main thread about any progress in my job thread?
Thanks for any help.
You can also use lock to implement a thread-safe JobManager class that tracks progress about the different worker threads. In this example I just maintain the active worker threads count, but this can be extended to your progress reports needs.
class JobManager
{
private object synchObject = new object();
private int _ActiveJobCount;
public int ActiveJobsCount
{
get { lock (this.synchObject) { return _ActiveJobCount; } }
set { lock (this.synchObject) { _ActiveJobCount = value; } }
}
public void Start(Action job)
{
var timer = new System.Timers.Timer(1000);
timer.Elapsed += (sender, e) =>
{
this.ActiveJobsCount++;
job();
this.ActiveJobsCount--;
};
timer.Start();
}
}
Example:
class Program
{
public static void Main(string[] args)
{
var manager = new JobManager();
manager.Start(() => Thread.Sleep(3500));
while (true)
{
Console.WriteLine(manager.ActiveJobsCount);
Thread.Sleep(250);
}
}
}
You can notify the main thread of progress through a callback method. That is:
// in the main thread
public void ProgressCallback(int jobNumber, int status)
{
// handle notification
}
You can pass that callback method to the worker thread when you invoke it (i.e. as a delegate), or the worker thread's code can "know" about it implicitly. Either way works.
The jobNumber and status parameters are just examples. You might want you use some other way to identify the jobs that are running, and you may want to use an enumerated type for the status. However you do it, be aware that the ProgressCallback will be called by multiple threads concurrently, so if you're updating any shared data structures or writing logging information, you'll have to protect those resources with locks or other synchronization techniques.
You can also use events for this, but keeping the main thread's event subscriptions up to date can be a potential problem. You also have the potential of a memory leak if you forget to unsubscribe the main thread from a particular worker thread's events. Although events would certainly work, I would recommend the callback for this application.
Use events. The BackgroundWorker class, for example, is designed specifically for what you have in mind.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
The ReportProgress function along with the ProgressChanged event are what you would use for progress updates.
pullJobTimer.Elapsed += (sender,e) =>
{
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += (s,e) =>
{
// Whatever tasks you want to do
// worker.ReportProgress(percentComplete);
};
worker.ProgressChanged += mainThread.ProgressChangedEventHandler;
worker.RunWorkerAsync();
};
If you don't mind depending on .NET 3.0 you can use the Dispatcher to marshal requests between threads. It behaves in a similar way to Control.Invoke() in Windows Forms but doesn't have the Forms dependency. You'll need to add a reference to the WindowsBase assembly though (part of .NET 3.0 and newer and is basis for WPF)
If you can't depend on .NET 3.0 then I'd say you were onto the correct solution from the beginning: Implement the ISynchronizeInvoke interface in your main class and pass that to the SynchronizingObject property of the Timer. Then your timer callback will be called on the main thread, which can then spawn BackgroundWorkers that checks the DB and runs any queued jobs. The jobs would report progress through the ProgressChanged event which will marshal the call to the main thread automatically.
A quick google search revealed this example on how to actually implement the ISynchronizeInvoke interface.

Update UI from multiple worker threads (.NET)

I have a pet project that I'm working on that has multiple worker threads. Outputting everything to the console is getting hard to follow, so I want to develop a UI that will have one output area per thread. I want to know the best way for the threads to send updates to the UI. I have two ideas:
1) Have each thread set a "DataUpdated" flag when new data is available, and have the UI periodically check for new data.
2) Create each thread with a callback to a UI Update(...) method to be called when new data becomes available.
I am currently leaning toward (2) for two reasons: I dislike the idea of "checking" each thread, and because this is my first multithreaded application and (2) seems simpler than it probably is. I want to know:
Which option is preferable in terms of simplicity and efficiency?
Do you have any tips for implementing (2) or something like it (i.e. more event-driven)?
You can easily implement (2) by creating BackgroundWorker components and doing the work in their DoWork handlers:
BackgroundWorker bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;
bw.DoWork += /* your background work here */;
bw.ProgressChanged += /* your UI update method here */;
bw.RunWorkerAsync();
Each BackgroundWorker can report progress to the UI thread by calling ReportProgress: although this is primarily designed for reporting progress on a bounded process, that's not mandatory -- you can pass your own custom data as well if that's what your UI update requires. You would call ReportProgress from your DoWork handler.
The nice thing about BackgroundWorker is that it takes care of a lot of messy cross-threading details for you. It also conforms to the event-driven model of updates which you (rightly) prefer to explicit callbacks.
In most cases the easiest thing to do would be to use the BackgroundWorker component as suggested in itowlson's answer, and I would strongly suggest using that approach if possible. If, for some reason, you can't use a BackgroundWorker component for your purpose, such as if you're developing with .Net 1.1 (yikes!) or with compact framework, then you might need to use an alternative approach:
With Winform controls you have to avoid modifying controls on any thread other than the thread that originally created the control. The BackgroundWorker component handles this for you, but if you aren't using that, then you can and should use the InvokeRequired property and Invoke method found on the System.Windows.Forms.Control class. Below is an example that uses this property and method:
public partial class MultithreadingForm : Form
{
public MultithreadingForm()
{
InitializeComponent();
}
// a simple button event handler that starts a worker thread
private void btnDoWork_Click(object sender, EventArgs e)
{
Thread t = new Thread(WorkerMethod);
t.Start();
}
private void ReportProgress(string message)
{
// check whether or not the current thread is the main UI thread
// if not, InvokeRequired will be true
if (this.InvokeRequired)
{
// create a delegate pointing back to this same function
// the Invoke method will cause the delegate to be invoked on the main UI thread
this.Invoke(new Action<string>(ReportProgress), message);
}
else
{
// txtOutput is a UI control, therefore it must be updated by the main UI thread
if (string.IsNullOrEmpty(this.txtOutput.Text))
this.txtOutput.Text = message;
else
this.txtOutput.Text += "\r\n" + message;
}
}
// a generic method that does work and reports progress
private void WorkerMethod()
{
// step 1
// ...
ReportProgress("Step 1 completed");
// step 2
// ...
ReportProgress("Step 2 completed");
// step 3
// ...
ReportProgress("Step 3 completed");
}
}
I vote for #2 as well but with BackgroundWorkers instead of System.Threading.Threads.
You can have your worker threads raise events and have the main UI thread add event handlers. You need to be careful you're not raising too many events as it could get ugly if your worker threads are raising multiple events per second.
This article gives a quick overview.
The preferred way to implement multithreading in your application is to use the BackgroundWorker component. The BackgroundWorker component uses an event-driven model for multithreading. The worker thread runs your DoWork event handler, and the thread that creates your controls runs your ProgressChanged and RunWorkerCompleted event handlers.
When you update your UI controls in the ProgressChanged eventhandler, they are automatically updated on main thread which will prevent you from getting crossthread exceptions.
Look here for an example on how to use the backgroundworker.
If you're creating your own threads (non BackgroundWorker or ThreadPool threads) you can pass a callback method from your main thread that's called from the worker thread. This also lets you pass arguments to the callback and even return a value (such as a go/no-go flag). In your callback you update the UI through the target control's Dispatcher:
public void UpdateUI(object arg)
{
controlToUpdate.Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal
, new System.Windows.Threading.DispatcherOperationCallback(delegate
{
controToUpdate.property = arg;
return null;
}), null);
}
}

Categories

Resources