c#中Lock(锁)的研究以及跨线程UI的操作
2014-11-25 13:46
344 查看
本文只针对C#中,多线程同步所用到的锁(lock)作为研究对象。由于想更直观的显示结果,所以,在做demo的时候,就把多线程通过事件操作UI的代码也写了出来,留作备忘和分享吧。
其实多线程的同步,使用同步锁的方法用了好多次,今天无意中看到MSDN中,建议用:
1 private static readonly object locker1 = new object();
2 private readonly object locker2 = new object();
备注:原文并没有加readonly,是我后来自己加进去的。
我不仅思考了一下他们的区别。
然后我写了一段代码进行测试,测试类代码如下:
复制代码
/// <summary>
/// 跨线程操作UI的时候传递的参数,本文为了显示消息,所以简单的封装了一个
/// </summary>
public class MyEventArgs : EventArgs
{
public readonly string Message = string.Empty;
public MyEventArgs(string msg)
{
this.Message = msg;
}
}
/// <summary>
/// 测试类,用于测试2种锁的区别
/// </summary>
public class LockTest
{
//2个锁
private static readonly object Locker1 = new object();
private readonly object Locker2 = new object();
/// <summary>
/// 跨线程操作UI的委托和事件
/// </summary>
public delegate void MessageEventHandler(object sender, MyEventArgs e);
public event MessageEventHandler MessageEvent;
public void OnMessage(MyEventArgs e)
{
if (this.MessageEvent != null) MessageEvent(this, e);
}
//要锁的变量,通过它可以看出2种锁在不同情况下的效果
private int num = 0;
//实例名字
private readonly string Name;
public LockTest(string name)
{
Name = name;
}
//第一种锁执行的方法
public void AddNum1()
{
lock (Locker1)
{
num = 0;
ShowMessage();
}
}
//第二种锁执行的方法
public void AddNum2()
{
lock (Locker2)
{
num = 0;
ShowMessage();
}
}
//锁内的一些操作,并通过事件,把关键的消息显示到主线程中的UI里
private void ShowMessage()
{
string msg = "";
for (int i = 0; i < 10; i++)
{
num += 1;
msg = string.Format("线程 [{0}],实例[{1}]中num的值是[{2}]", Thread.CurrentThread.Name, this.Name, num);
OnMessage(new MyEventArgs(msg));
Thread.Sleep(100);
}
msg = string.Format("======线程 [{0}]执行完毕======", Thread.CurrentThread.Name);
OnMessage(new MyEventArgs(msg));
}
}
复制代码
测试用的类写完了,开始测试:
首先测试单个实例、多线程,2种锁的区别:
private void button1_Click(object sender, EventArgs e)
{
LockTest test = new LockTest("LockTest 1");
test.MessageEvent += new LockTest.MessageEventHandler(MessageCallBack);
listBox1.Items.Clear();
for (int i = 0; i <= 2; i++)
{
Thread a = new Thread(new ThreadStart(test.AddNum1));
a.Name = i.ToString();
a.Start();
}
}
private void button2_Click(object sender, EventArgs e)
{
LockTest test = new LockTest("LockTest 1");
test.MessageEvent += new LockTest.MessageEventHandler(MessageCallBack);
listBox1.Items.Clear();
for (int i = 0; i <= 2; i++)
{
Thread a = new Thread(new ThreadStart(test.AddNum2));
a.Name = i.ToString();
a.Start();
}
}
输出结果一模一样:
得出结论:如果对一个实例,多线程访问的时候,2种锁是没有区别的。
下面是测试多个实例的情况(静态锁):
复制代码
private void button3_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
for (int i = 0; i <= 2; i++)
{
LockTest test = new LockTest("LockTest " + i.ToString());
test.MessageEvent += new LockTest.MessageEventHandler(MessageCallBack);
Thread a = new Thread(new ThreadStart(test.AddNum1));
a.Name = i.ToString();
a.Start();
}
}
复制代码
得到结果:
得出结论,在静态锁面前,线程依旧要排队,虽然不是一个实例,但是锁是唯一的,线程只认锁,所以线程并没有并发!
继续测试(非静态的锁):
复制代码
private void button4_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
for (int i = 0; i <= 2; i++)
{
LockTest test = new LockTest("LockTest " + i.ToString());
test.MessageEvent += new LockTest.MessageEventHandler(MessageCallBack);
Thread a = new Thread(new ThreadStart(test.AddNum2));
a.Name = i.ToString();
a.Start();
}
}
复制代码
得到的结果:
得出结论:非静态锁的时候,多线程并发了,一起在工作。
其实,测试的结果之前也能猜想出来,只不过,不测试下,心里总是觉得没底,呵呵,测试完了,也就彻底释然了!
窗体中,用于事件回调,显示到UI里的代码在这里:
复制代码
delegate void MessageHandler(string msg);
public void MessageCallBack(object sender, MyEventArgs e)
{
MessageHandler handler = new MessageHandler(ShowMessage);
this.Invoke(handler, new object[] { e.Message });
}
public void ShowMessage(string msg)
{
this.listBox1.Items.Add(msg);
}
其实多线程的同步,使用同步锁的方法用了好多次,今天无意中看到MSDN中,建议用:
1 private static readonly object locker1 = new object();
2 private readonly object locker2 = new object();
备注:原文并没有加readonly,是我后来自己加进去的。
我不仅思考了一下他们的区别。
然后我写了一段代码进行测试,测试类代码如下:
复制代码
/// <summary>
/// 跨线程操作UI的时候传递的参数,本文为了显示消息,所以简单的封装了一个
/// </summary>
public class MyEventArgs : EventArgs
{
public readonly string Message = string.Empty;
public MyEventArgs(string msg)
{
this.Message = msg;
}
}
/// <summary>
/// 测试类,用于测试2种锁的区别
/// </summary>
public class LockTest
{
//2个锁
private static readonly object Locker1 = new object();
private readonly object Locker2 = new object();
/// <summary>
/// 跨线程操作UI的委托和事件
/// </summary>
public delegate void MessageEventHandler(object sender, MyEventArgs e);
public event MessageEventHandler MessageEvent;
public void OnMessage(MyEventArgs e)
{
if (this.MessageEvent != null) MessageEvent(this, e);
}
//要锁的变量,通过它可以看出2种锁在不同情况下的效果
private int num = 0;
//实例名字
private readonly string Name;
public LockTest(string name)
{
Name = name;
}
//第一种锁执行的方法
public void AddNum1()
{
lock (Locker1)
{
num = 0;
ShowMessage();
}
}
//第二种锁执行的方法
public void AddNum2()
{
lock (Locker2)
{
num = 0;
ShowMessage();
}
}
//锁内的一些操作,并通过事件,把关键的消息显示到主线程中的UI里
private void ShowMessage()
{
string msg = "";
for (int i = 0; i < 10; i++)
{
num += 1;
msg = string.Format("线程 [{0}],实例[{1}]中num的值是[{2}]", Thread.CurrentThread.Name, this.Name, num);
OnMessage(new MyEventArgs(msg));
Thread.Sleep(100);
}
msg = string.Format("======线程 [{0}]执行完毕======", Thread.CurrentThread.Name);
OnMessage(new MyEventArgs(msg));
}
}
复制代码
测试用的类写完了,开始测试:
首先测试单个实例、多线程,2种锁的区别:
private void button1_Click(object sender, EventArgs e)
{
LockTest test = new LockTest("LockTest 1");
test.MessageEvent += new LockTest.MessageEventHandler(MessageCallBack);
listBox1.Items.Clear();
for (int i = 0; i <= 2; i++)
{
Thread a = new Thread(new ThreadStart(test.AddNum1));
a.Name = i.ToString();
a.Start();
}
}
private void button2_Click(object sender, EventArgs e)
{
LockTest test = new LockTest("LockTest 1");
test.MessageEvent += new LockTest.MessageEventHandler(MessageCallBack);
listBox1.Items.Clear();
for (int i = 0; i <= 2; i++)
{
Thread a = new Thread(new ThreadStart(test.AddNum2));
a.Name = i.ToString();
a.Start();
}
}
输出结果一模一样:
得出结论:如果对一个实例,多线程访问的时候,2种锁是没有区别的。
下面是测试多个实例的情况(静态锁):
复制代码
private void button3_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
for (int i = 0; i <= 2; i++)
{
LockTest test = new LockTest("LockTest " + i.ToString());
test.MessageEvent += new LockTest.MessageEventHandler(MessageCallBack);
Thread a = new Thread(new ThreadStart(test.AddNum1));
a.Name = i.ToString();
a.Start();
}
}
复制代码
得到结果:
得出结论,在静态锁面前,线程依旧要排队,虽然不是一个实例,但是锁是唯一的,线程只认锁,所以线程并没有并发!
继续测试(非静态的锁):
复制代码
private void button4_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
for (int i = 0; i <= 2; i++)
{
LockTest test = new LockTest("LockTest " + i.ToString());
test.MessageEvent += new LockTest.MessageEventHandler(MessageCallBack);
Thread a = new Thread(new ThreadStart(test.AddNum2));
a.Name = i.ToString();
a.Start();
}
}
复制代码
得到的结果:
得出结论:非静态锁的时候,多线程并发了,一起在工作。
其实,测试的结果之前也能猜想出来,只不过,不测试下,心里总是觉得没底,呵呵,测试完了,也就彻底释然了!
窗体中,用于事件回调,显示到UI里的代码在这里:
复制代码
delegate void MessageHandler(string msg);
public void MessageCallBack(object sender, MyEventArgs e)
{
MessageHandler handler = new MessageHandler(ShowMessage);
this.Invoke(handler, new object[] { e.Message });
}
public void ShowMessage(string msg)
{
this.listBox1.Items.Add(msg);
}
相关文章推荐
- c#中Lock(锁)的研究以及跨线程UI的操作
- !!c# 委托与多线程 -- 相比background来说,本方法针对当需要通过异步代理发起UI操作,而后线程中进行sleep操作的时使用
- android 访问网络不能在主线程中进行以及在线程中操作UI的解决方法
- (六)线程--分别用lock以及Interlocked和Monitor类实现线程的临界区操作(互斥)(示例下载)
- (六)线程--分别用lock以及Interlocked和Monitor类实现线程的临界区操作(互斥)(示例下载)
- C# 跨线程操作UI(界面)
- C#线程相关问题总结:基本操作及UI控件交互
- (六)线程--分别用lock以及Interlocked和Monitor类实现线程的临界区操作(互斥)(示例下载)
- c#非委托方式在子线程里操作UI控件(实际上运算逻辑在子线程,更新还是在主线程,解决了UI界面无响应的问题)
- android4.0以上访问网络不能在主线程中进行以及在线程中操作UI的解决方法
- 分析SpinnerActivityTest中有关控件操作以及UI线程问题
- C#线程相关问题总结:基本操作及UI控件交互
- RCP 非UI线程调用UI操作
- MD5加密简介以及C#下的操作实现
- c# 线程同步: 详解lock,monitor,同步事件和等待句柄以及mutex
- c# 线程同步:详解lock,monitor,同步事件和等待句柄以及mutex
- c# 线程同步: 详解lock,monitor,同步事件和等待句柄以及mutex(ZT)
- c# 线程同步: 详解lock,monitor,同步事件和等待句柄以及mutex
- c# 线程同步: 详解lock,monitor,同步事件和等待句柄以及mutex
- C#中利用委托实现多线程跨线程操作