[简介]
常用网名: 猪头三
出生日期: 1981.XX.XX
QQ联系: 643439947
个人网站: 80x86汇编小站 https://www.x86asm.org
编程生涯: 2001年~至今[共22年]
职业生涯: 20年
开发语言: C/C++、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python
开发工具: Visual Studio、Delphi、XCode、Eclipse、C++ Builder
技能种类: 逆向 驱动 磁盘 文件
研发领域: Windows应用软件安全/Windows系统内核安全/Windows系统磁盘数据安全/macOS应用软件安全
项目经历: 磁盘性能优化/文件系统数据恢复/文件信息采集/敏感文件监测跟踪/网络安全检测
[序言]
上一篇"[原创][5]探究C#多线程开发细节-利用AutoResetEvent类解决多线程循环轮询假同步的问题.-CSDN博客"文章结尾提到过, 可以用ConcurrentDictionary<T,T>代替ConcurrentQueue<T> 管理AutoResetEvent事件会更加方便. 为什么会方便呢? 第一: 省去了ConcurrentQueue<T>的ToArray()转换问题. 第二: 通过ConcurrentDictionary<T,T>的TKey去查找目标线程的对应AutoResetEvent事件会更加方便, 代码可读性更强.
[下面是完整的代码]
为了更能直观地表显示出多线程的交互关系, 我扩展了更多的信息在界面上显示而且还配上了截图, 大家可以一边阅读源码, 一边观看下方的GIF图片, 慢慢领悟多线程的核心逻辑.
private ConcurrentDictionary<int, AutoResetEvent> mpr_cdic_ThreadEvent = new ConcurrentDictionary<int, AutoResetEvent>();
public class Thread_Run
{
public int mpu_int_ThreadIndex;
private Action<int> mpr_action_UpdateWaitInfo;
private Action<int> mpr_action_UpdateRunInfo;
private ConcurrentDictionary<int, AutoResetEvent> mpr_cdic_ThreadEvent;
private AutoResetEvent mpr_event_State;
public Thread_Run(Action<int> action_param_UpdateWaitInfo,
Action<int> action_param_UpdateRunInfo,
ref ConcurrentDictionary<int, AutoResetEvent> cdic_param_ThreadEvent,
object obj_param_EventState)
{
mpr_action_UpdateWaitInfo = action_param_UpdateWaitInfo;
mpr_action_UpdateRunInfo = action_param_UpdateRunInfo;
mpr_cdic_ThreadEvent = cdic_param_ThreadEvent;
mpr_event_State = (AutoResetEvent)obj_param_EventState;
}
public int mpu_fun_ShowIndex()
{
return mpu_int_ThreadIndex;
}
public void mpu_pro_StartThread()
{
Thread class_Thread = new Thread(Thread_Exe);
class_Thread.Start();
}
private void Thread_Exe()
{
// 模拟工作
Random class_Random = new Random();
Thread.Sleep(class_Random.Next(1, 11)*1000);
if (mpu_int_ThreadIndex != 0)
{
//调用委托方法来更新UI
mpr_action_UpdateRunInfo?.Invoke(mpu_int_ThreadIndex);
// 如果不是第一个线程则直接等待
mpr_event_State.WaitOne();
}
//调用委托方法来更新UI
mpr_action_UpdateWaitInfo?.Invoke(mpu_int_ThreadIndex);
// 通知当前线程的下一个线程放弃等待,可直接返回
// 比如当前是1号线程,那么它的下一个就是2号线程
AutoResetEvent event_Next;
if (mpr_cdic_ThreadEvent.TryGetValue(mpu_int_ThreadIndex + 1, out event_Next))
{
event_Next.Set();
}
}
}// End Thread_Run()
public Form_Main()
{
InitializeComponent();
}
public void mpu_pro_UpdateWaiteInfo(int int_param_ThreadIndex)
{
if (InvokeRequired)
{
this.Invoke((MethodInvoker)delegate {
lb_WaitInfo.Text += (Environment.NewLine + string.Format("{0} 号线程已正常退出.", int_param_ThreadIndex));
});
}
}
public void mpu_pro_UpdateRunInfo(int int_param_ThreadIndex)
{
if (InvokeRequired)
{
this.Invoke((MethodInvoker)delegate {
lb_RunInfo.Text += (Environment.NewLine + string.Format("{0} 号线程已完成工作, 正等待 {1} 号线程退出...", int_param_ThreadIndex, int_param_ThreadIndex-1));
});
}
}
private void Bn_StartThread_Click(object sender, EventArgs e)
{
// 启动10个线程
for (int int_Index = 0; int_Index < 10; int_Index++)
{
var var_ThreadEvent = new AutoResetEvent(false);
mpr_cdic_ThreadEvent.TryAdd(int_Index, var_ThreadEvent);
Thread_Run class_ThreadRun = new Thread_Run(mpu_pro_UpdateWaiteInfo, mpu_pro_UpdateRunInfo, ref mpr_cdic_ThreadEvent, var_ThreadEvent);
class_ThreadRun.mpu_int_ThreadIndex = int_Index;
class_ThreadRun.mpu_pro_StartThread();
}
}
}
[截图欣赏]