110,565
社区成员
发帖
与我相关
我的任务
分享
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private LockTest lt = new LockTest();
private void button1_Click_1(object sender, EventArgs e)
{
Task t = new TaskFactory().StartNew(() => lt.testc(this.textBox1,this.label1));
}
private void button2_Click(object sender, EventArgs e)
{
Task t = new TaskFactory().StartNew(() => lt.testb(this.textBox1, this.label2));
}
}
public class LockTest
{
private static object locker = new object();
private int count = 1;
public void testc(TextBox tb,Label lable)
{
lock (locker)
{
tb.Invoke(new Action(() => tb.AppendText("aaaa\r\n")));
var sw = new Stopwatch();
sw.Start();
while (sw.ElapsedMilliseconds < 2000)
{
Thread.Sleep(100);
lable.Invoke(new Action(() => lable.Text = count.ToString()));
count++;
}
tb.Invoke(new Action(() => tb.AppendText("axaxax\r\n")));
}
}
public void testb(TextBox tb,Label lable)
{
lock (locker)
{
tb.Invoke(new Action(() => tb.AppendText("bbbb\r\n")));
var sw = new Stopwatch();
sw.Start();
while (sw.ElapsedMilliseconds < 2000)
{
Thread.Sleep(100);
lable.Invoke(new Action(() => lable.Text = count.ToString()));
count++;
}
tb.Invoke(new Action(() => tb.AppendText("bxbxbx\r\n")));
}
}
}
刚修改了一下。这样就能看出。lock还是有用的。lock (locker)
{
tb.Invoke(new Action(() => tb.AppendText("xxxxxxxxxxxx\r\n")));
var sw = new Stopwatch();
sw.Start();
while (sw.ElapsedMilliseconds < 2000)
{
Thread.Sleep(1);
Application.DoEvents();
}
tb.Invoke(new Action(() => tb.AppendText("aaaaaaaaaaaa\r\n")));
}
下次发的时候。带上标签,否则很难看。
我是这么理解的。不知道说的对不对,如果不注释,很容易理解。就是while函数阻止了第二个方法的运行。这个你应该可以理解。lock关键字根本就没用。去掉lock关键字也是一样的效果。
注释掉点两次的话。lock我觉得还是起作用的,这里关键是这个Application.Doevent()函数。看过msdn的解释。说实在的很不形象,我个人是这么理解的。这个函数执行的时候,就算有长方法使得界面假死,也可以允许其他控件或者信息进行操作。而已经在运行的长时间程序会被暂停。下面是我的测试例子:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private LockTest lt = new LockTest();
private void button1_Click_1(object sender, EventArgs e)
{
lt.testc(textBox1);
}
private void button2_Click(object sender, EventArgs e)
{
lt.testb(textBox1);
}
}
public class LockTest
{
private static object locker = new object();
public void testc(TextBox tb)
{
lock (locker)
{
tb.Invoke(new Action(() => tb.AppendText("aaaa\r\n")));
var sw = new Stopwatch();
sw.Start();
while (sw.ElapsedMilliseconds < 2000)
{
Thread.Sleep(1);
Application.DoEvents();
}
tb.Invoke(new Action(() => tb.AppendText("axaxax\r\n")));
}
}
public void testb(TextBox tb)
{
lock (locker)
{
tb.Invoke(new Action(() => tb.AppendText("bbbb\r\n")));
var sw = new Stopwatch();
sw.Start();
while (sw.ElapsedMilliseconds < 2000)
{
Thread.Sleep(1);
Application.DoEvents();
}
tb.Invoke(new Action(() => tb.AppendText("bxbxbx\r\n")));
}
}
}
为了区分两个长时间方法,我用了两个方法,被一个锁lock。点击第一个运行第二个方法,这个时候点击第二个按钮,第一个方法会被暂停。去执行第二个方法。当第二个方法执行完的时候,第一个方法才会被执行。。。。
当然也看出来了。去掉lock。。。程序表现是一样的。。。。
所以~~~楼主的问题跟DoEvent()函数看似是没关系的。。。。
接下来我就开始想为什么被lock之后,语句还是可以执行呢。(就是连续点击两次。textbox的异步修改功能是重复出现的)想了一下。觉得还是Doenvent的问题。于是我又修改了代码。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private LockTest lt = new LockTest();
private void button1_Click_1(object sender, EventArgs e)
{
lt.testc(textBox1,label1);
}
private void button2_Click(object sender, EventArgs e)
{
lt.testb(textBox1,label2);
}
}
public class LockTest
{
private static object locker = new object();
private int count = 1;
public void testc(TextBox tb,Label lable)
{
lock (locker)
{
tb.Invoke(new Action(() => tb.AppendText("aaaa\r\n")));
var sw = new Stopwatch();
sw.Start();
while (sw.ElapsedMilliseconds < 2000)
{
Thread.Sleep(100);
lable.Text = count.ToString();
count++;
Application.DoEvents();
}
tb.Invoke(new Action(() => tb.AppendText("axaxax\r\n")));
}
}
public void testb(TextBox tb,Label lable)
{
lock (locker)
{
tb.Invoke(new Action(() => tb.AppendText("bbbb\r\n")));
var sw = new Stopwatch();
sw.Start();
while (sw.ElapsedMilliseconds < 2000)
{
Thread.Sleep(100);
lable.Text = count.ToString();
count++;
Application.DoEvents();
}
tb.Invoke(new Action(() => tb.AppendText("bxbxbx\r\n")));
}
}
}
这下就很清楚了。。。。。。。还是Doenvet的问题!!!!这个函数,通俗来说。就是当他运行的时候,你可以用程序处理其他消息队列中的事情。但是只要处理,那么现在的消息就往后推~~~~其实就是把现在的线程和正在处理的消息分开,处理你让他的处理的另外一个消息。。。。。lock还是起了作用。但是被这个函数直接把线程干掉了。。。。。。void A()
{
lock (locker)
{
lock(locker)
{
// 可以运行到这里。
}
}
}
而 Application.DoEvents会运行UI的消息循环:
public void testc(TextBox tb)
{
// ...
Application.DoEvents();
// ...
}
UI的消息循环的结果就是 button1_Click有机会得到运行。
因此,出现了在UI线程下的button1_Click嵌套运行,而按照lock的分析,同一个线程下的lock是可以直接获得的。