Executing on a background thread using BeginInvoke
I'm trying out multithreading but I cant figure out why the the piece of code below blocks the UI when task.Execute() is called?
public class Task<TRes>
{
private Func<TRes> _func;
public Task(Func<TRes> func)
{
_func = func;
}
public TRes Execute()
{
var iasync = _func.BeginInvoke(null, null);
return _func.EndInvoke(iasync);
}
}
I'm not trying to solve any problem in particular. Just wondering why the UI blocks when it hits Thread.Sleep even though the current thread (the one that was put to "sleep") is a ThreadPool t开发者_C百科hread (and not the main UI thread). Below is a button click event that uses the Task class.
var task = new Task<string>(() =>
{
var start = DateTime.Now;
var isBackGround = Thread.CurrentThread.IsBackground ;
var isThreadPool = Thread.CurrentThread.IsBackground;
Thread.Sleep(5000);
return String.Format("Start {0} : End {1}", start, DateTime.Now);
}
);
this.label1.Text = task.Execute();
The problem is that calling EndInvoke
blocks the calling thread until the function finishes executing. What you're doing is spawning a worker thread to execute your _func
and then blocking until that worker finishes. I would recommend using the callback parameter of BeginInvoke
. And if you're doing GUI stuff, don't forget about Dispatcher.
Come to think of it, I wouldn't recommend starting multithreading with GUIs at all, since it can be a real pain. Start off with console applications so you can get the hang of the whole multithreading thing, then move to GUIs, where things can get painful.
void Main()
{
var cookies = new IAsyncResult[10];
Action action = delegate
{
// I'm going to print out a bunch of numbers here
for (int i = 0; i < 100; ++i)
Console.WriteLine(i);
}
for (int i = 0; i < cookies.Length; ++i)
cookies[i] = action.BeginInvoke(null, null);
// with all 10 threads executing, you'll see numbers print out in some crazy,
// unpredictable order...this line will come out somewhere in the mess (or maybe
// before it...who knows?)
Console.WriteLine("All threads started!");
// we wait for each of the workers to finish executing here:
foreach (var c in cookies)
action.EndInvoke(c);
// and this will always be printed last, thereby demonstrating that EndInvoke
// causes the calling thread to wait for the action to finish
Console.WriteLine("Done!");
}
I know that this does't directly answer your question, but I just wanted to point you towards the System.Threading.Tasks namespace, if you are using .Net 4.0. The Task(of T) is really well documented and performs as expected.
-Josh
精彩评论