[C#] 多线程总结(结合进度条)

时间:2023-03-09 08:15:34
[C#] 多线程总结(结合进度条)

线程生命周期(来源 w3cschool)

  1. 未启动状态:当线程实例被创建但 Start 方法未被调用时的状况。
  2. 就绪状态:当线程准备好运行并等待 CPU 周期时的状况。
  3. 不可运行状态
    • 已经调用 Sleep 方法
    • 已经调用 Wait 方法
    • 通过 I/O 操作阻塞
  4. 死亡状态:当线程已完成执行或已中止时的状况。

Thread 常用方法:

  • public void Interrupt()    中断处于 WaitSleepJoin 线程状态的线程。
  • public void Join()         在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻塞调用线程,直到某个线程终止为止。
  • public void Start()        开始一个线程
  • public static void Sleep(int millisecondsTimeout)    让线程暂停一段时间

一 普通线程

分为两种,一种是不需要给子线程传参数,Thread t = new Thread(new ThreadStart(void () target)); 另一种是要给子线程传一个参数,Thread t = new Thread(new ParameterizedThreadStart(void (object) target));

 // 普通线程
private void btn1_Click(object sender, EventArgs e)
{
progressBar.Value = 0;
Thread tt = new Thread(new ThreadStart(DoWork1));
tt.Name = "不带参数普通线程";
tt.Start();
Thread t = new Thread(new ParameterizedThreadStart(DoWork2));
t.Name = "带参数普通线程";
t.IsBackground = true;
t.Start(100);
_msg += "当前线程的执行状态:" + t.IsAlive + "\r\n";
_msg += "当前托管线程的唯一标识:" + t.ManagedThreadId + "\r\n";
_msg += "线程名称:" + t.Name + "\r\n";
_msg += "当前线程的状态:" + t.ThreadState;
MessageBox.Show("消息:\r\n" + _msg, "提示", MessageBoxButtons.OK);
}
// 线程方法
private void DoWork1()
{
for (int i = 0; i < 100; i++)
{
// 跨线程访问 UI,BeginInvoke 采用异步委托
progressBar.BeginInvoke(new EventHandler((sender, e) =>
{
progressBar.Value = i;
}), null);
}
}
// 线程方法
private void DoWork2(object obj)
{
for (int i = 0; i < (int)obj; i++)
{
progressBar.BeginInvoke(new EventHandler((sender, e) =>
{
progressBar.Value = i;
}), null);
}
}

普通线程

二  线程池

public static bool QueueUserWorkItem(WaitCallback);

public static bool QueueUserWorkItem(WaitCallback, object);

线程池默认为后台线程(IsBackground)

 private void btn3_Click(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(DoWork2, 100);
// 或者
ThreadPool.QueueUserWorkItem((s) =>
{
int minWorkerThreads, minCompletionPortThreads, maxWorkerThreads, maxCompletionPortThreads;
ThreadPool.GetMinThreads(out minWorkerThreads, out minCompletionPortThreads);
ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxCompletionPortThreads);
MessageBox.Show(String.Format("WorkerThreads = {0} ~ {1}, CompletionPortThreads = {2} ~ {3}",
minWorkerThreads, maxWorkerThreads, minCompletionPortThreads, maxCompletionPortThreads));
DoWork2(100);
});
}
// 线程方法
private void DoWork2(object obj)
{
for (int i = 0; i < (int)obj; i++)
{
// Thread.Sleep(50);
progressBar.BeginInvoke(new EventHandler((sender, e) =>
{
progressBar.Value = i;
}), null);
}
}

线程池

三  BackgroundWorker

 private void btn4_Click(object sender, EventArgs e)
{
progressBar.Value = 0;
BackgroundWorker bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;// 是否报告进度更新
// 线程执行
bw.DoWork += new DoWorkEventHandler((obj, args) =>
{
for (int i = 0; i < 100; i++)
{
bw.ReportProgress(i);
}
});
// UI主线程显示进度
bw.ProgressChanged += (obj, progressChangedEventArgs) =>
{
progressBar.Value = progressChangedEventArgs.ProgressPercentage;
};
// 线程执行完成后的回调函数
bw.RunWorkerCompleted += (obj, runWorkerCompletedEventArgs) =>
{
MessageBox.Show("子线程执行完成!");
};
if (!bw.IsBusy)
{
bw.RunWorkerAsync();
}
}

BackgroundWorker

三  Task(.NET 4.0以上版本)

参考博客 http://www.cnblogs.com/luxiaoxun/p/3280146.html

 private void btn5_Click(object sender, EventArgs e)
{
progressBar.Value = 0;
Task<bool> t = new Task<bool>(maxValue => DoWork((int)maxValue), progressBar.Maximum);
t.Start();
t.Wait();
// 任务完成后继续延续任务
Task cwt = t.ContinueWith(task => MessageBox.Show("The result is " + t.Result));
}
// 线程方法
private bool DoWork(int maxValue)
{
for (int n = 0; n < maxValue; n++)
{
progressBar.BeginInvoke(new EventHandler((sender, e) =>
{
progressBar.Value = n;
}), null);
} return true;
}

Task

四  异步委托

参考博客 http://www.cnblogs.com/luxiaoxun/p/3280146.html

 public delegate string MyDelegate(object arg);

 private void btn6_Click(object sender, EventArgs e)
{
MyDelegate myDelegate = new MyDelegate(DoWork3);
IAsyncResult result = myDelegate.BeginInvoke(100, DoWork2Callback, "回调函数参数"); // 异步执行完成
string resultStr = myDelegate.EndInvoke(result);
} // 线程函数
private string DoWork3(object arg)
{
for (int n = 0; n < (int)arg; n++)
{
progressBar.BeginInvoke(new EventHandler((sender, e) =>
{
progressBar.Value = n;
}), null);
} return "Finished";
} // 异步回调函数
private void DoWork2Callback(IAsyncResult arg)
{
MessageBox.Show(arg.AsyncState.ToString());
}

异步委托

五  附 跨线程访问UI之 SynchronizationContext (同步上下文)

 private void btn2_Click(object sender, EventArgs e)
{
SynchronizationContext context = SynchronizationContext.Current;
new Thread(() =>
{
for (int i = 0; i < 100; i++)
{
// Send方法是发送一个异步请求消息
//context.Send((s) =>
//{
// progressBar.Value = i;
//}, null);
// Post方法是发送一个同步请求消息
context.Post((s) =>
{
progressBar.Value = i;
}, null);
}
}).Start();
}

SynchronizationContext

六  参考资料:

☆多线程讲解 http://www.w3cschool.cc/csharp/csharp-multithreading.html

http://www.cnblogs.com/luxiaoxun/p/3280146.html