C#中的同步异步
根据项目中用到的做个总结
1.0 Mutex
概述:用于内部进程的“原始”同步。
跳过sample看后面的备注:2个或以上线程需要同时获取一个共享资源时,该类可以保证一个时间只有一个线程占用获取该资源。注意 exclusive的修饰,表明了具有排他性访问的能力。
问题1,多个线程运行是否有超时处理机制?
可以。WaitTimeout来指定等待时间。
问题2,能否用于一台机器的多个进程之间?
可以。通过Mutex的名字来实现多个进程之间,使用同一个Mutex,实现互斥访问资源。同时也支持 OpenExisting的方式打开现有的Mutex.
Mutex Class (System.Threading) | Microsoft Learn
samples
APP1和app2 是相同的代码,TEST1为互斥对象名字,每隔2秒模拟一次访问共享资源,
Mutex _mutex = new Mutex(false, "TEST1");// 不同进程间使用同一个名字
delegate void HandleLogMsg(string msg);
HandleLogMsg _handleLogMsg;
public MainWindow()
{
InitializeComponent();
_handleLogMsg = Updatetext;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(() => {
ThreadProc();
});
}
private void ThreadProc()
{
while (true)
{
_mutex.WaitOne();
var msg = $"App2: {DateTime.Now:yyyy-MM-dd HH:mm:ss,fff}{Environment.NewLine}";
this.Dispatcher.Invoke(_handleLogMsg, msg);
Thread.Sleep(2000);
_mutex.ReleaseMutex();
}
}
private void Updatetext(string msg)
{
_tbMultiline.Text += msg;
_tbMultiline.ScrollToEnd();
}

2秒内只能有一个访问共享资源,通过此处的时间可知App1有时可以连续获得共享访问资源的资格,
2.0 EventWaitHandle
EventWaitHandle Class (System.Threading) | Microsoft Learn
直接看Remarks的说明, 该类允许多个线程彼此通过信号来通信。典型地比如,一个或多个线程会被阻塞,直到一个非阻塞的线程设置了“绿灯” 即调用了Set 方法,绿灯后,一个或多个被阻塞的线程被释放去执行逻辑。
同上,与AutoResetEvent 和 ManualResetEvent相比,可以适用于不通进程间的同步。
为了解决保证上面2个进程交替访问共享资源,测试代码如下
APP1和2分别添加代码:
EventWaitHandle _ewh2 = new EventWaitHandle(false, EventResetMode.AutoReset, "TEST2"); EventWaitHandle _ewh3 = new EventWaitHandle(false, EventResetMode.AutoReset, "TEST3");
//APP2添加
private void ThreadProc2() { while (true) { _ewh2.WaitOne(); var msg = $"App2: {DateTime.Now:yyyy-MM-dd HH:mm:ss,fff}{Environment.NewLine}"; this.Dispatcher.Invoke(_handleLogMsg, msg); Thread.Sleep(2000); _ewh3.Set(); } }
//APP1添加
private void ThreadProc2()
{
_ewh2.Set();//允许APP2先执行,从而触发交替访问
while (true)
{
_ewh3.WaitOne();
var msg = $"App1: {DateTime.Now:yyyy-MM-dd HH:mm:ss,fff}{Environment.NewLine}";
this.Dispatcher.Invoke(_handleLogMsg, msg);
Thread.Sleep(2000);
//EventWaitHandle.SignalAndWait(_ewh2, _ewh3);
_ewh2.Set();
}
}

测试结果:App2先执行,符合预期;App2和app1,时间间隔都在4秒,说明交替执行。
备注:二者均在74行,时间间隔为4.008、4.009秒,为误差秒,
3.0 信号用于控制线程的 暂停 和 继续
增加如下代码到项目App1,
ManualResetEvent _ewh3_1 = new ManualResetEvent(true); CancellationToken _token; CancellationTokenSource _tokenSource = new CancellationTokenSource();
private void ThreadProc3()
{
while (true)
{
if (_token.IsCancellationRequested)
return;
_ewh3_1.WaitOne();
var msg = $"App1: {DateTime.Now:yyyy-MM-dd HH:mm:ss,fff}{Environment.NewLine}";
this.Dispatcher.Invoke(_handleLogMsg, msg);
Thread.Sleep(2000);
}
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
_ewh3_1.Reset();
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
_ewh3_1.Set();
}
ManualResetEvent(true),true 表明初始信号为允许执行,会影响waitone的行为为。
FALSE:所有调用了WaitOne的线程将进入阻塞状态,直到某些线程调用了Set方法;
TRUE:所有调用了WaitOne的线程将不进入阻塞状态,自由执行WaitOne后的逻辑;
测试结果:持续以每2秒输出,点击暂停后停止动作,点击继续后继续输出。
浙公网安备 33010602011771号