c# - await Task.Run(() => semaphore.WaitOne()) 有什么问题吗?

标签 c# .net multithreading thread-safety task-parallel-library

标题说明了一切。 await Task.Run(() => semaphore.WaitOne()); 有什么问题吗? System.Threading.Semaphore 不是线程仿射的,所以我认为不会有问题。我知道 SemaphoreSlim 类可用,但我需要进行跨进程同步,而 SemaphoreSlim 不会这样做。

或者我可以/应该创建我自己的 WaitHandle 自定义类型吗?

最佳答案

如果您在此处等待信号量时试图保持 UI 响应,这可能是有道理的,但有一个问题: "Semaphores don't have owners" 。如果您在两个进程之间共享信号量,而另一个进程没有调用 Semaphore.Release() 就崩溃了,共享资源的所有权将丢失。剩余的进程可能无法再次获取它。

国际海事组织,Mutex语义在这里更合适,但是使用 Mutex 你需要线程亲和性。也许,您可以获取互斥体、访问资源并在同一线程上释放它:

await Task.Factory.StartNew(() => 
{
    mutex.WaitOne();
    try
    {
        // use the shared resource
    }
    finally
    {
        mutex.ReleaseMutex(); 
    }
}, TaskCreationOptions.LongRunnning);

如果那不可能(例如,因为您需要在主 UI 线程上访问共享资源),您可以为互斥量使用专用线程。这可以通过自定义任务调度程序来完成,例如斯蒂芬·图布的 StaTaskScheduler使用 numberOfThreads:1(在这种情况下,辅助线程不必成为 STA):

using (var scheduler = new StaTaskScheduler(numberOfThreads: 1))
{
    await Task.Factory.StartNew(
        () => mutex.WaitOne(), 
        CancellationToken.None,
        TaskCreationOptions.None,
        scheduler);
    try
    {
        // use the shared resource on the UI thread
    }
    finally
    {
        Task.Factory.StartNew(
            () => mutex.ReleaseMutex(), 
            CancellationToken.None,
            TaskCreationOptions.None,
            scheduler).Wait();
    }
}

已更新,如果您担心 WinRT(即 .NET for Windows Store Apps)或 Windows Phone,请使用 Task.Factory.StartNew w/TaskCreationOptions。 LongRunning 仍然存在,您可以使用它代替 new Thread()StaTaskScheduler 或类似我的 ThreadWithSerialSyncContext 的东西每当您需要具有亲和性的后台线程时。

关于c# - await Task.Run(() => semaphore.WaitOne()) 有什么问题吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23118177/

相关文章:

c# - 多家公司的数据库架构

C#:const 变量在二进制文件中的位置

java - 具有两种同步方法的线程安全性,一种是静态的,一种是非静态的

c++ - 并发问题 : how to have only one thread go through critical section

c# - 我可以使用页面流式传输图像,而不是发送 ImageUrl 吗?

c# - 仅当我从组合框中选择一个项目时才执行操作

c# - 构建 azure Pipeline 中的某些库时出现 "nuget restore"问题

.net - BinaryReader ReadByte() 是否超时?

c# - Windows 中公钥和私钥容器的位置?

c - 是否有可能在c中同时运行主线程及其子线程