Zan*_*ski 7 .net c# multithreading thread-safety task-parallel-library
标题说明了一切.有什么不对await Task.Run(() => semaphore.WaitOne());吗?System.Threading.Semaphore不是线程仿射,所以我不认为会有问题.我知道这个SemaphoreSlim类是可用的,但是我需要进行跨进程同步,而SemaphoreSlim不是那样做.
或者我可以/应该创建自己的自定义类型WaitHandle吗?
如果您试图在等待信号灯时使UI保持响应,这可能是有道理的,但是有一个陷阱:“信号灯没有所有者”。如果您在两个进程之间共享信号量,而另一个进程崩溃而没有调用Semaphore.Release(),则对共享资源的所有权将丢失。剩余的过程可能无法再次获取它。
IMO,这里的Mutex语义会更合适,但是Mutex您需要线程关联。也许,您可以获取互斥体,访问资源并在同一线程上释放它:
await Task.Factory.StartNew(() =>
{
mutex.WaitOne();
try
{
// use the shared resource
}
finally
{
mutex.ReleaseMutex();
}
}, TaskCreationOptions.LongRunnning);
Run Code Online (Sandbox Code Playgroud)
如果那是不可能的(例如,因为您需要访问主UI线程上的共享资源),则可以将专用线程用于互斥量。这可以使用自定义任务调度程序来完成,例如Stephen Toub的StaTaskSchedulerwith 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();
}
}
Run Code Online (Sandbox Code Playgroud)
更新后,如果您担心WinRT(即Windows Store Apps的.NET)或Windows Phone,则Task.Factory.StartNeww / TaskCreationOptions.LongRunning仍然存在,只要需要有亲和力的后台线程,就可以使用它代替new Thread()with StaTaskScheduler或与之类似的东西ThreadWithSerialSyncContext。