C# 多线程编码范例
最近不少朋友问关于C#多线程的操作,我们以疯狂代码工作室为例,写个系列教程供大家参考
这是一个系列,我们先从简单的开始
我们以CrazyCoder工作室为例,现在6个工作室成员
因工作需要,工作室成员需要做一个项目,因为是多个人做,那么我们用多线程来做
首先定义成员类 UserInfo(表示成员信息),还有一个方法Work()表示工作
public class UserInfo
{
private string _name;
///
/// 用户名称
///
public string Name
{
get { return _name; }
set { _name = value; }
}
///
/// 线程执行具体方法 注意:必须是Void类型,不能为静态方法
/// by crzycoder http://www.crazycoder.cn
///
public void Work()
{
//这里写要做的工作代码
}
}
现在开始写线程代码
public class WorkThread
{
///
/// 线程执行代码
/// by crzycoder http://www.crazycoder.cn
///
public void CrazyCoderThread()
{
//假设工作室6名成员开始工作
for (int i = 1; i <= 6; i++)
{
UserInfo u = new UserInfo();
u.Name = "疯狂工作室成员" + i.ToString();
Thread t = new Thread(u.Work);
t.Start();
}
}
}
这是一个简单的多线程例子,调用方法 new CrazyCoderThread().ProjectThread();
即可
//crazycoder原创,转载请注明出处
我们解决了简单的多线程问题了,现在问题出来了,现在有个project对疯狂工作室很重要,我们能实现多个成员共同工作但是如何实现任务分配呢?
提供一个解决方案,答案是在成员类上,我们对UserInfo类做如下改动
public class UserInfo
{
private string _name;
///
/// 用户名称
///
public string Name
{
get { return _name; }
set { _name = value; }
}
private string _workDetail;
///
/// 代码细节 可以理解为代码分工,这个属性里我们对CrazyCoder工作室成员进行工作分工
/// by crazycoder http://www.crazycoder.cn
///
public string WrokDetail
{
get { return _workDetail; }
set { _workDetail = value; }
}
///
/// 线程执行具体方法 注意:必须是Void类型,不能为静态方法
/// 这里实现了线程分工
/// by crazycoder http://www.crazycoder.cn
///
public void Work()
{
//这里写要做的工作代码
if (_workDetail == "负责写数据操作类代码")
{
//开始写底层代码
}
else
{
//这里写其他判断语句
}
}
}
同样我们对线程类改造
///
/// C#多线程系列教程 疯狂代码工作室出品
/// by crazycoder http://www.crazycoder.cn
///
public class CrazyCoderThread
{
///
/// 线程执行代码
/// by crazycoder http://www.crazycoder.cn
///
public void ProjectThread()
{
//假设工作室6名成员开始工作
for (int i = 1; i <= 6; i++)
{
UserInfo u = new UserInfo();
u.Name = "疯狂工作室成员" + i.ToString();
//这里对线程成员分工
u.WrokDetail = "负责写数据操作类代码";
//线程初始化
Thread t = new Thread(u.Work);
//线程开始
t.Start();
}
}
}
到这里,我们已经可以实现对线程的分工了,希望能给大家帮助
道理很简单,我们就是在代码定义的时候对线程进行了分工
仅作入门之用参考
多线程在执行的时候调试很麻烦,特别是在运行之后出错,这里我们就需要对线程进行日志处理
多线程运行时出错时有可能会引起整个线程池的崩溃,从而引起进程的意外关掉,那么在写程序的时候我们一方面要在可能出错的地方try{}catche{},另外一个好习惯就是写日志,发一个日之类
发一个日志函数
///
/// 写入日志 by crazycoder
/// http://www.crazycoder.cn/首发
///
///
日志文件名,不需要带路径///
日志内容,单位为行public static void WriteLog(string fileName,string content)
{
//获取日志文件物理路径
string path = Util.CrazyCoderGetMapPath(fileName);
try
{
if (!System.IO.File.Exists(path))
{
StreamWriter sw = System.IO.File.CreateText(path);
sw.WriteLine("---日志开始---" + DateTime.Now.ToString());
sw.Flush();
sw.Close();
}
StreamWriter sw2 = System.IO.File.AppendText(path);
//每个日志写一行 crazycoder.cn
sw2.WriteLine("--" + DateTime.Now.ToString() + "---" + content);
sw2.Flush();
sw2.Close();
}
catch
{
}
}
为了兼容web与Form应用程序,我们采用了一个GetMapPath方法,贴上代码
///
/// 获得当前绝对路径 by crazycoder.cn 含web和winform应用程序方法
///
///
指定的路径/// 绝对路径
public static string CrazyCoderGetMapPath(string strPath)
{
if (HttpContext.Current != null)
{
//如果是web
return HttpContext.Current.Server.MapPath(strPath);
}
else //非web程序引用
{
if (strPath.StartsWith("~/"))
strPath = strPath.Substring(2);
else if (strPath.StartsWith("/"))
strPath = strPath.Substring(1);
return System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, strPath);
}
}
通过这两个方法,我们在线程开始和结束的地方写上日志
同时在容易出错的地方,在try catch的地方写日志,就很容易知道多线程出错的地方,并方便的进行调试
实现线程通讯的例子有很多种,我们这里介绍几个简单的例子给大家看
第二篇我们对线程进行了简单的分工,但是存在一个问题,小B并不知道小A的工作完成了没有,并且小B线程需要在小A的工作完成之后才能接着做下面的工作,但是小A在机子的办公室里懒得出来,他只在办公室里说我的工作完成了,但是小B小C都不知道,小B和小C在自己的办公室里听不到小A说的话(我们把每个线程比作一个独立的办公室),如此下来,小B和小C只能闲置下来,我们想办法要让小B和小C知道小A的工作已经完成了!
老板急了,这个时候需要考虑发工资的问题,让人闲着的话是巨大的人力资源和财力的浪费,老板就想这个时候我们最好的办法就是给成员们的办公室里办个电话,可以互相通电话,电话总机放在我这里,为了避免成员偷懒,我让总机把他们的工作状态都记录下来,给成员们每个动作都进行了侦听,方便高效的考核和发工资。
老板这人比较更懒,想一下上面的方法虽然可以解决他们偷懒的问题,但是每次让我去问太麻烦了,我更懒得一个电话一个电话的问,算了,恶心他们,通知小A,如果你工作做完了,就通知总机,小B和小C定时打给总机问小A是否完成了工作,那么我们就通过电话总机的自动应答来协调A,B,C之间的工作吧
这样代码就很简单了,我们这样定义
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace CrazyCoder.多线程教程
{
public class 老板
{
private static List<员工> _电话总机记录;
///
///各个员工的工作状态
///
public static List<员工> 电话总机记录
{
get { return _电话总机记录; }
set { _电话总机记录 = value; }
}
public void 多线程干活()
{
员工 a = new 员工();
员工 b = new 员工();
员工 c = new 员工();
a.工作内容 = "A";
b.工作内容 = "B";
c.工作内容 = "C";
//开始创建监听对象
_电话总机记录 = new List<员工>();
_电话总机记录.Add(a);
_电话总机记录.Add(b);
_电话总机记录.Add(c);
//开始派遣到个子的办公室
Thread threadA = new Thread(a.干活);
Thread threadB = new Thread(b.干活);
Thread threadC = new Thread(c.干活);
//干活吧
threadA.Start();
threadB.Start();
threadC.Start();
}
}
public class 员工
{
private string _工作内容;
public string 工作内容
{
get{return _工作内容;}
set{_工作内容 =value;}
}
private string _state;
public string State
{
get{return _state;}
set{_state =value;}
}
public void 干活()
{
//分工
if (_工作内容 == "A")
{
老板.电话总机记录[0]._state = "干活中";
//小A干活
//干活完毕
老板.电话总机记录[0]._state = "完毕";
//完成后有
//ThreadA.Start();
}
if (_工作内容 == "B")
{
//等待小A完成工作
while (老板.电话总机记录[0]._state != "完毕")
{
//休息1秒
}
//干活
}
if (_工作内容 == "C")
{
//等待小A完成工作
while (老板.电话总机记录[0]._state != "完毕")
{
//休息1秒
}
//干活
}
}
}
}
- 上一篇 »java怎么使用多线程解决主线程提前结束问题?
- 下一篇 »PHP中的,伪多线程与多进程