它工作正常用下面的代码:为什么没有任务<TResult>。结果在这种情况下工作?
private void button1_Click(object sender, EventArgs e)
{
Task<int> t = test(5);
Console.WriteLine(t.Result);
}
private Task<int> test(int n)
{
return Task.Run(() =>
{
return n;
});
}
但是,如果我换用异步方法的测试方法,这是行不通的:
private Task<int> test(int n)
{
return Task.Run(() =>
{
return n;
});
}
public async Task<int> wrap()
{
return await test(5);
}
private void button1_Click(object sender, EventArgs e)
{
Task<int> t = wrap();
Console.WriteLine(t.Result);
}
窗体失去响应。如果我用等待,它按预期工作。
更新1: 这两个答案都是正确的,但我只能标记为答案。基于对这个问题的理解,我做了进一步的测试。我用ConfigureAwait在包装方法 离开延续到比UI其他线程运行:
public async Task<int> wrap()
{
return await test(5).ConfigureAwait(false);
}
它工作正常。然后,我测试了这一点:
public async Task<int> wrap()
{
int i = await test(5).ConfigureAwait(false);
int j = i + await test(3);
return j;
}
它的工作对第一次当我点击该按钮,但在第二次点击再次发生死锁。如果我测试(3),这样的后添加ConfigureAwait(假):
public async Task<int> wrap()
{
int i = await test(5).ConfigureAwait(false);
int j = i + await test(3).ConfigureAwait(false);
return j;
}
它的工作再次,但这并不道理给我。由于第一个ConfigureAwait(false),wrap()中的以下所有同步部分都应该在非UI线程上运行。我不明白为什么第二个ConfigureAwait(false)是必要的。
UPDATE2:
private Task<int> test(int n)
{
return Task.Run(() =>
{
Console.WriteLine("test(" + n + "): " + System.Threading.Thread.CurrentThread.ManagedThreadId);
return n;
});
}
public async Task<int> wrap()
{
Console.WriteLine("1.wrap(): " + System.Threading.Thread.CurrentThread.ManagedThreadId);
int i = await test(5).ConfigureAwait(false);
Console.WriteLine("2.wrap(): " + System.Threading.Thread.CurrentThread.ManagedThreadId);
int j = i + await test(3);
Console.WriteLine("3.wrap(): " + System.Threading.Thread.CurrentThread.ManagedThreadId);
return j;
}
private void button1_Click(object sender, EventArgs e)
{
try
{
Console.WriteLine("1.button1_Click(): " + System.Threading.Thread.CurrentThread.ManagedThreadId);
var t = wrap();
Console.WriteLine("2.button1_Click(): " + System.Threading.Thread.CurrentThread.ManagedThreadId);
Console.WriteLine(t.Result);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
几个点击后,形式冻结,并输出结果是:
1.button1_Click(): 8
1.wrap(): 8
test(5): 13
2.wrap(): 8
2.button1_Click(): 8
test(3): 13
令我惊讶的是, “2.wrap():” 运行在与“1.wrap():”相同的线程中,而不是“test(5)”。看起来,ConfigureAwait(false)之后的代码也可以跳回到UI线程。