考虑下面这个异步函数,它修改了一个非线程安全的列表:
async Task AddNewToList(List<Item> list)
{
// Suppose load takes a few seconds
Item item = await LoadNextItem();
list.Add(item);
}
简单来说:这样做安全吗?
我关心的是,一个人可能会调用异步方法,而当它在加载(无论是在另一个线程上还是作为I/O操作)时,调用者可能会修改列表。
假设调用者正在执行list.Clear()的过程中,例如,突然Load方法完成了!会发生什么?
任务会立即中断并运行 list.Add(item);
代码吗?还是它会等待主线程完成所有已安排的CPU任务(即等待Clear()完成)后再运行代码?
编辑:既然我已经在下面回答了自己的问题,那么这里有一个额外的问题:为什么?为什么它不等待CPU绑定操作完成而是立即中断呢?看起来这样做毫无意义,因为队列本身是完全安全的。
编辑:这是我自己测试的另一个示例。注释指示了执行顺序。我很失望!
TaskCompletionSource<bool> source;
private async void buttonPrime_click(object sender, EventArgs e)
{
source = new TaskCompletionSource<bool>(); // 1
await source.Task; // 2
source = null; // 4
}
private void buttonEnd_click(object sender, EventArgs e)
{
source.SetResult(true); // 3
MessageBox.Show(source.ToString()); // 5 and exception is thrown
}
async void
,则所有赌注都将失效。 - John Wusource = null
是一个连续。你必须小心地使用TaskCompletionSource。 - Mike Zboray