C# 进程同步/信令的互斥替代方案,支持异步?
除了C# 进程同步/信令的互斥替代方案,支持异步?,c#,mutex,C#,Mutex,除了互斥之外,还有什么方法可以以容错方式同步两个进程吗?请容忍我 有一个过程a,它有点不稳定,它需要在后台启动过程B并继续。若进程A成功地完成了它的任务,它需要通知进程B进行处理,然后继续(它不终止,线程被重用)。如果进程A因异常、终止等原因死亡,进程B需要快速检测并自行处理。进程A不是一个“进程”,而是一个由不同主机执行的库,因此进程B不能只等待进程A的名称消失 输入互斥 这里,一个由测试夹具表示的进程,如果成功,它将调用TestFixtureTearDown并继续,或者测试运行程序可能会被终
互斥
之外,还有什么方法可以以容错方式同步两个进程吗?请容忍我
有一个过程a,它有点不稳定,它需要在后台启动过程B并继续。若进程A成功地完成了它的任务,它需要通知进程B进行处理,然后继续(它不终止,线程被重用)。如果进程A因异常、终止等原因死亡,进程B需要快速检测并自行处理。进程A不是一个“进程”,而是一个由不同主机执行的库,因此进程B不能只等待进程A的名称消失
输入互斥
这里,一个由测试夹具表示的进程,如果成功,它将调用TestFixtureTearDown
并继续,或者测试运行程序可能会被终止,并且永远不会执行TestFixtureTearDown
。与实际进程一样,testfixturedeardown
可能被运行TestFixtureSetUp
并创建互斥体的线程调用,因此ReleaseMutex
有时抛出ApplicationException:从未同步的代码块调用对象同步方法。
TestFixtureTearDown
中强制ReleaseMutex
,还是以其他方式放弃互斥ApplicationException
之外,Mutex感觉像是一个非常优雅的解决方案信号量没有线程关联。您可以在不同的线程上释放信号量,而不是在不同的线程上获取信号量。使用计数为1的信号量。我最后混合使用了
互斥锁
、线程
和手动重置事件
。对于未来的谷歌用户,这里有一个详细的测试:
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
namespace MutexResetEvent.Tests
{
public class Class1
{
private Mutex _mutex;
private Thread _thread;
private Process _process;
private ManualResetEvent _event;
[SetUp]
public void SetUp()
{
Console.WriteLine("SetUp: #{0}", Thread.CurrentThread.ManagedThreadId);
_event = new ManualResetEvent(false);
_thread = new Thread(() =>
{
Console.WriteLine("Thread: #{0}", Thread.CurrentThread.ManagedThreadId);
_mutex = new Mutex(true, "MutexResetEvent");
_process = new Process
{
StartInfo =
{
FileName = "MutexResetEvent.Worker.exe",
//UseShellExecute = false,
//RedirectStandardOutput = true
}
};
//_process.OutputDataReceived += (o, a) => Console.WriteLine(a.Data);
_process.Start();
//_process.BeginOutputReadLine();
while (!_event.WaitOne(1000))
Console.WriteLine("Thread: ...");
Console.WriteLine("Thread: #{0}", Thread.CurrentThread.ManagedThreadId);
_mutex.ReleaseMutex();
_process.WaitForExit();
});
}
[Test]
public void Test()
{
Console.WriteLine("Test: #{0}", Thread.CurrentThread.ManagedThreadId);
_thread.Start();
for (var i = 0; i < 3; i++)
{
Console.WriteLine("Test: ...");
Thread.Sleep(1000);
}
/*
if (Guid.NewGuid().GetHashCode() % 3 == 0)
Environment.Exit(1);
//*/
}
[TearDown]
public void TearDown()
{
Console.WriteLine("TearDown: #{0}", Thread.CurrentThread.ManagedThreadId);
Task.Run(() =>
{
Console.WriteLine("Task: #{0}", Thread.CurrentThread.ManagedThreadId);
_event.Set();
//_thread.Join();
}).Wait();
for (var i = 0; i < 3; i++)
{
Console.WriteLine("TearDown: ...");
Thread.Sleep(1000);
}
}
}
}
谢谢,我一直在考虑信号量,但找不到任何关于如何复制
放弃的MutexException
行为的信息,即当启动进程意外终止并且没有发出完成信号时。这一切都发生在一边是心跳,另一边是超时。它有一个废弃的状态/事件吗?我没想到。我不认为信号灯是答案。下一个想法是让库使用所选的任何IPC机制将其运行的PID传输到“watcher”进程。然后,您可以等待进程终止。
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var mutex = Mutex.OpenExisting("foo");
// Start doing stuff
try { mutex.WaitOne(); }
catch (AbandonedMutexException) { }
finally { mutex.ReleaseMutex(); }
// Finish doing stuff
}
}
}
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
namespace MutexResetEvent.Tests
{
public class Class1
{
private Mutex _mutex;
private Thread _thread;
private Process _process;
private ManualResetEvent _event;
[SetUp]
public void SetUp()
{
Console.WriteLine("SetUp: #{0}", Thread.CurrentThread.ManagedThreadId);
_event = new ManualResetEvent(false);
_thread = new Thread(() =>
{
Console.WriteLine("Thread: #{0}", Thread.CurrentThread.ManagedThreadId);
_mutex = new Mutex(true, "MutexResetEvent");
_process = new Process
{
StartInfo =
{
FileName = "MutexResetEvent.Worker.exe",
//UseShellExecute = false,
//RedirectStandardOutput = true
}
};
//_process.OutputDataReceived += (o, a) => Console.WriteLine(a.Data);
_process.Start();
//_process.BeginOutputReadLine();
while (!_event.WaitOne(1000))
Console.WriteLine("Thread: ...");
Console.WriteLine("Thread: #{0}", Thread.CurrentThread.ManagedThreadId);
_mutex.ReleaseMutex();
_process.WaitForExit();
});
}
[Test]
public void Test()
{
Console.WriteLine("Test: #{0}", Thread.CurrentThread.ManagedThreadId);
_thread.Start();
for (var i = 0; i < 3; i++)
{
Console.WriteLine("Test: ...");
Thread.Sleep(1000);
}
/*
if (Guid.NewGuid().GetHashCode() % 3 == 0)
Environment.Exit(1);
//*/
}
[TearDown]
public void TearDown()
{
Console.WriteLine("TearDown: #{0}", Thread.CurrentThread.ManagedThreadId);
Task.Run(() =>
{
Console.WriteLine("Task: #{0}", Thread.CurrentThread.ManagedThreadId);
_event.Set();
//_thread.Join();
}).Wait();
for (var i = 0; i < 3; i++)
{
Console.WriteLine("TearDown: ...");
Thread.Sleep(1000);
}
}
}
}
using System;
using System.Threading;
namespace MutexResetEvent.Worker
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Worker: #{0}", Thread.CurrentThread.ManagedThreadId);
var mutex = Mutex.OpenExisting("MutexResetEvent");
try
{
while (!mutex.WaitOne(1000))
Console.WriteLine("Worker: ...");
}
catch (AbandonedMutexException)
{
Console.WriteLine("Worker: AbandonedMutexException");
}
Console.WriteLine("Worker: #{0}", Thread.CurrentThread.ManagedThreadId);
mutex.ReleaseMutex();
Console.WriteLine("Worker: WOO HOO");
Console.ReadLine();
}
}
}