1 post tagged “threading”
Problem
I was working on a remoting project for an assignment and we came
across a problem in 2.0. As of 2.0 you cannot make cross-thread calls
to a windows forms control. This means that if you are doing an
asyncronous call, most likely, unless your polling the async result, it
will come back on a different thread and you cannot change a windows
form or the controls on it without coming back to the origonal thread.
This is fine if you are making all of your asyncronous calls on the
actual form (You just need to call the Invoke method), but if you are
seperating the asyncronous logic from the presentation layer (Which is
recommended), any results processed from that logic can be difficult to
update in windows forms. Fortunatly, there is a solution within the
AsyncOperation class. I recommend looking into this class if you are
doing anything thread related, but I created a wrapper around the class
to make it a bit easier to use. Hopefully, it will be as useful to you
as it was for me.
How it works
My wrapper simply operates the AsyncOperation class. When you
instantiate the object, you instantiate a copy of the AsyncOperation
class which will hold a reference to the initial thread you
instantiated it on. This means you can make cross-thread calls to it,
and it will execute the code on the origonal thread it was instantiated
on. So, if you instantiate this class within your dll's constructor,
any events or code that you execute that need to work on the windows
forms thread you just call in an anonymous delegate under the
Syncronize method.
Place this class somewhere in your project.
using System;
using System.ComponentModel;
using System.Threading;/// <summary>
/// Class that allows multithread syncronization
/// from asyncronous calls. Anything wrapped with
/// the syncronize method will be executed on the
/// same thread as where the AsyncSyncronizer
/// is instantiated.
/// </summary>
/// <example>
/// Instantiate on thread you want to use
/// AsyncSyncronizer sync = new AsyncSyncronizer();
///
/// // Run on the code you would like to execute.
/// this.sync.Syncronize(
/// delegate
/// {
/// /*Code to Execute*/
/// });
///</example>
public class AsyncSyncronizer
{
/// <summary>
/// Delegate pointing to code executed
/// within the Syncronize method.
/// </summary>
public delegate void AsyncDelegate();/// <summary>
/// Async operation which will push execution
/// to the proper thread.
/// </summary>
private AsyncOperation operation;/// <summary>
/// Creates an object of the AsyncSyncronizer
/// Everything wrapped within the Syncronize
/// method will be executed by default on the
/// thread this is instantiated on. In order to change
/// the thread, run SetThread.
/// </summary>
public AsyncSyncronizer()
{
// Set to this thread.
this.SetThread();
}/// <summary>
/// Sets the thread code will by syncronized to
/// to the current thread running.
/// </summary>
public void SetThread()
{
this.operation =
AsyncOperationManager.CreateOperation(null);
}/// <summary>
/// Runs code within this method on the
/// thread either set by set thread or
/// where the object was instantiated.
/// </summary>
/// <param name="render">The code
/// to execute on the specified thread.</param>
public void Syncronize(
AsyncDelegate render)
{
this.operation.Post(new SendOrPostCallback(delegate(object state)
{
render();
}), null);
this.operation.OperationCompleted();
}
}