如果我们锁定(TaskInstance)不共享会发生什么?

问题描述 投票:0回答:1

一个例子:

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());
}
  1. 当 myContinuedTask 锁定 myTask 时,就像锁定(this)一样,对吗?

  2. 如果实例在此代码的控制之外使用,这不是一个好主意,对吗?

  3. 如果此实例仅在这段代码的控件内使用,是否有可能 myContinuedTask 永远不会获得锁,从而保持等待状态?

我知道任务是由 TaskScheduler 管理的。我不知道这是否对任务实例进行了一些锁定,这可能会导致死锁? (我需要更多信息)

  1. 任务的Id字段不保证是唯一的。它是一个 int,所以最多可以存在 4^32 个任务,对吧?这看起来确实很低。 是每个进程、每个线程、每个会话吗?
.net locking task scheduled-tasks
1个回答
0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.