2010-10-12 69 views
0

我正在尝试多线程,但我无法弄清楚为什么在调用task.Execute()时,下面的代码块会阻塞UI?使用BeginInvoke在后台线程上执行

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); 
    } 
} 

我不想特别解决任何问题。只是想知道为什么即使当前线程(放置到“睡眠”的那个线程是ThreadPool线程(而不是主UI线程))时它阻塞Thread.Sleep。以下是使用Task类的按钮单击事件。

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(); 

回答

1

问题是调用EndInvoke会阻止调用线程,直到该函数完成执行。你正在做的是产生一个工作者线程来执行你的_func,然后阻塞,直到该工人完成。我会建议使用BeginInvoke的回调参数。如果你在做图形用户界面的话,不要忘记Dispatcher

想一想,我不会推荐用GUI开始多线程,因为它可能是一个真正的痛苦。从控制台应用程序开始,让您可以掌握整个多线程的东西,然后转到GUI,在那里可能会变得很痛苦。

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!"); 
} 
0

我知道这个开不直接回答你的问题,但我只是想为您指出在System.Threading.Tasks命名空间,如果你使用的是.NET 4.0。 T(T)的任务确实有很好的文档记录,并按预期执行。

-Josh

相关问题