线程阻止UI

Jam*_*ery 6 c# task-parallel-library

我在Nutshell中关注了C#中的一个例子.根据文本,下面的代码应该是非阻塞的,但我发现表单将在5秒过后才会显示.

private void Form1_Load(object sender, EventArgs e)
{
    var tcs = new TaskCompletionSource<int>();

    new Thread(() => {Thread.Sleep(5000); tcs.SetResult(42); }).Start();

    Task<int> task = tcs.Task;
    MessageBox.Show(task.Result.ToString());
}
Run Code Online (Sandbox Code Playgroud)

我觉得这与Thread.Sleep()有关,而不是让新线程处于休眠状态,而是让主线程处于休眠状态.

为什么它会阻止UI线程?

Ser*_*kiy 11

当你试图获得任务task.Result主线程的结果将被阻止,直到任务完成它的执行(即结果将可用).使用task.ContinueWith,如果你不想等待异步操作完成:

Task<int> task = tcs.Task;
task.ContinueWith(t => {         
     MessageBox.Show(t.Result.ToString());
});
Run Code Online (Sandbox Code Playgroud)

顺便说一句,.NET 4.5中有很好的功能可以在任务完成时恢复挂起操作 - 异步方法:

private async void Form1_Load(object sender, EventArgs e)
{
    var tcs = new TaskCompletionSource<int>();
    new Thread(() => { Thread.Sleep(2000); tcs.SetResult(42); }).Start();
    int result = await tcs.Task;
    MessageBox.Show(result.ToString());
}
Run Code Online (Sandbox Code Playgroud)

在开始等待任务结果后,此方法将立即对调用者进行控制.当结果可用时,方法将继续执行并显示消息.

实际上正如@Servy在注释中指出的那样,返回的异步方法void不是很好的实践(例如用于错误处理),但有时可以将它们用于事件处理程序.


It'*_*ie. 5

当你调用Task.Result.ToString()(in MessageBox.Show)时,Task类有一个机制,在实际给你结果之前等待任务完成(因为它实际上没有它直到Task完成.这是我的证明:

private void Form1_Load(object sender, EventArgs e)
{
    var tcs = new TaskCompletionSource<int>();

    new Thread(() => {Thread.Sleep(5000); tcs.SetResult(42); }).Start();

    Task<int> task = tcs.Task;
    Thread.Sleep(2500);
    MessageBox.Show("Waited for 2.5secs on UI thread.");
    MessageBox.Show(task.Result.ToString());
}
Run Code Online (Sandbox Code Playgroud)

您将看到它在消息框之前显示2.5秒消息框,其中包含42.(事实上,在此之前的2.5秒).

你在寻找的是:

private void Form1_Load(object sender, EventArgs e)
{
    var tcs = new TaskCompletionSource<int>();

    new Thread(() => {Thread.Sleep(5000); tcs.SetResult(42); }).Start();

    Task<int> task = tcs.Task;
    task.ContinueWith(t => MessageBox.Show(t.Result.ToString()));
}
Run Code Online (Sandbox Code Playgroud)

不会冻结UI线程.