一个例子:
try
{
var myTask = Task.Run(async () =>
{
await Task.Delay(1);
});
myTask.ContinueWith(myContinuedTask =>
{
lock (myTask)
{
Task.Delay(1).Wait();
Console.WriteLine(myContinuedTask.Id);
}
});
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
当 myContinuedTask 锁定 myTask 时,就像锁定(this)一样,对吗?
如果实例在此代码的控制之外使用,这不是一个好主意,对吗?
如果此实例仅在这段代码的控件内使用,是否有可能 myContinuedTask 永远不会获得锁,从而保持等待状态?
我知道任务是由 TaskScheduler 管理的。我不知道这是否对任务实例进行了一些锁定,这可能会导致死锁? (我需要更多信息)
1)当 myContinuedTask 锁定 myTask 时,就像锁定(this)一样,对吧?
不;与
lock(myContinuedTask)
相同。
2)如果实例在此代码的控制之外使用,这不是一个好主意,对吗?
正确。您希望尽可能始终锁定私有或局部范围变量。另外,我建议有一个单独的
object
,仅用作锁,没有其他用途。
3)如果这个实例仅在这段代码的控制范围内使用,myContinuedTask是否有可能永远不会获得锁,从而保持等待状态?我知道任务是由 TaskScheduler 管理的。我不知道这是否对任务实例进行了一些锁定,这可能会导致死锁? (我需要更多信息)
当然,这是可能的。一旦公开用于锁定的对象实例,就有可能出现死锁。
4) 不保证任务的 Id 字段是唯一的。它是一个 int,所以最多可以存在 4^32 个任务,对吧?这看起来确实很低。是每个进程、每个线程、每个会话……?
他们只是开始复制,仅此而已。不用担心。
代码的其他问题包括:
ContinueWith
代替 await
。Task.Delay(..).Wait()
代替 Thread.Sleep
。此外,由于这是异步代码,您可能需要考虑使用
SemaphoreSlim
而不是 lock
。