Mutex或Semaphore用于两个不同的线程

时间:2017-01-25 03:27:02

标签: c# multithreading tcp async-await

我有两个async-await连接到同一个TCP端口。

RSP20000ms轮询一次。

SP每个500ms轮询一次。

另一种方法RP,无论何时调用它都会轮询,因此它可以是随机的。

现在,只要几次调用RP,整个系统就会冻结。

我想知道信号量 Mutex 在这种情况下是否更合适,我应该如何使用它。

我查看了信号量的示例,但似乎大多数都使用了一种方法,但尝试同时运行其中的5种。我如何在两种不同的方法中使用它们?

static SemaphoreSlim _sem = new SemaphoreSlim(1, 1);
public async void RSP()
{
    await Task.Run(() =>
    {
        while (true)
        {
            _sem.Wait();
            //DoWork
            _sem.Release();
            Thread.Sleep(20000);
        }
    }
    );
}

public async void SP(CancellationToken token)
{
    await Task.Run(() =>
    {
        while (true)
        {                
            try
            {
                if (token.IsCancellationRequested)
                {
                    return;
                }        
               _sem.Wait();
               //DoWork
               _sem.Release();
            }
            catch (Exception)
            {
                if (token.IsCancellationRequested)
                {
                    return;
                }
                break;
            }
            Thread.Sleep(500);
        }
    });
}

1 个答案:

答案 0 :(得分:0)

当您(默默地)忽略Exception处理程序中的catch时,会发生不好的事情。

try
{
   //...
   _sem.Wait();
   //if an exception happens here
   //you won't know about it because
   //logic in the catch means it will
   //be ignored.
   //Even worse... the line below won't be called
   _sem.Release();
}
catch (Exception)
{
    //...
    break; //oh s**t. how will we ever know?
}

这是死锁的完美配方。

如何改进?

try
{
   //...
   _sem.Wait();
   try
   {
       //do work
   }
   finally
   {
       _sem.Release(); //called, even if there's an exception
   }
}
catch (Exception)
{
    //...
    //this is just sloppy. never ignore ALL exceptions
    //fix this.
    break; 
}

顺便说一下,您似乎正在进行大量的同步阻止操作,并将它们与async await混合使用。这并不意味着它的使用方式。如果您没有使用任务/异步网络方法,那么您可以使用Thread.Sleep来使用await Task.DelaySemaphoreSlim提供了使用WaitAsync方法等待信号量的任务/异步支持。您的代码中可能没有任何内容需要通过等待,睡眠或同步IO来停止执行。正确学习异步并停止使用等待或睡眠的线程来捆绑你的ThreadPool。