simple asynchronous method invocation using a background worker (want feedback on my implementation)
I wanted a way to call a method asynchronously and have a function be fired upon completion. This is partially inspired by AJAX calls in web applications. Is my implementation ok? Is there a better way to do this?
public static class Tools
{
public static void RunAsync(Action function, Action callback)
{
BackgroundWorker worker = new BackgroundWorker();
worker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e)
开发者_如何学运维{
callback();
};
worker.DoWork += delegate(object sender, DoWorkEventArgs e)
{
function();
};
worker.RunWorkerAsync();
}
}
Is there a good way to extend this to work with functions that take arguments and have return values?
Thanks!
How about changing that Action
delegate to Action<T>
.
public static class Tools
{
public static void RunAsync<T>(Action<T> function, Action callback, T parameter)
{
BackgroundWorker worker = new BackgroundWorker();
worker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e)
{
callback();
};
worker.DoWork += delegate(object sender, DoWorkEventArgs e)
{
function(parameter);
};
worker.RunWorkerAsync();
}
}
Thanks Brian and jscharf for the answers! I constructed a set of functions using generics as suggested.
Below is one of them that takes two arguments and and has a return value:
public static void RunAsync<T1, T2, TResult>(Func<T1, T2, TResult> function, T1 param1, T2 param2, Action<TResult> callback)
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += delegate(object sender, DoWorkEventArgs e)
{
e.Result = function(param1, param2);
};
worker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e)
{
TResult result = (TResult)e.Result;
callback(result);
};
worker.RunWorkerAsync();
}
You could use it to do something like this (this was my goal):
Tools.RunAsync<string, string>(Tools.ComputeSHA1Hash, filePath,
delegate(string computedHash)
{
// do some processing with the hash
}
);
DoWorkEventArgs has an Argument member of type object
that you can use to pass in arguments to your functions.
You can pass a data structure in e this way and use it to contain your parameters, and even your "return" values if you like. Do this by passing your state object into RunWorkerAsync(), e.g:
SomeCustomStateObject obj = new SomeCustomStateObject("foo", 1);
RunAsync(obj, func, callback);
// ...
public static void RunAsync(object target, Action function, Action callback)
{
BackgroundWorker worker = new BackgroundWorker();
worker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e)
{
callback();
};
worker.DoWork += delegate(object sender, DoWorkEventArgs e)
{
function(e);
};
worker.RunWorkerAsync(obj);
}
function would look something like this:
void function(DoWorkEventArgs e)
{
SomeCustomStateObject obj = (SomeCustomStateObject)e.Argument;
// ... do some stuff with obj
// ... maybe put our "return" values back into obj
}
精彩评论