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的地方写日志,就很容易知道多线程出错的地方,并方便的进行调试
实现线程通讯的例子有很多种,我们这里介绍几个简单的例子给大家看