使用BeginInvoke在后台线程上执行

时间:2010-10-12 02:17:49

标签: c# multithreading

我正在尝试多线程,但是我无法弄清楚为什么下面的代码会在调用task.Execute()时阻止UI?

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

我不是要特别解决任何问题。只是想知道为什么UI在遇到Thread.Sleep时阻塞,即使当前线程(被置于“睡眠”的线程)是一个ThreadPool线程(而不是主UI线程)。下面是一个使用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();

2 个答案:

答案 0 :(得分:1)

问题是调用EndInvoke会阻塞调用线程,直到函数完成执行。你正在做的是产生一个工作线程来执行你的_func然后阻塞直到那个工人完成。我建议使用BeginInvoke的回调参数。如果您正在做GUI内容,请不要忘记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!");
}

答案 1 :(得分:0)

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

-Josh