using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace try1
{
public partial class Form1 : Form
{
volatile bool start_a = false;
volatile bool start_b = false;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (start_a == false)
{
button1.Text = "Running";
start_a = true;
Thread thread2 = new Thread(new ThreadStart(th1));
thread2.Start();
}
else
{
button1.Text = "Click to start";
start_a = false;
}
}
void th1()
{
int a=0;
while (start_a==true)
{
label1.Invoke((MethodInvoker)(() => label1.Text = Convert.ToString(a)));
Thread.Sleep(50);
a++;
}
}
void th2()
{
int b = 0;
while (start_b == true)
{
label2.Invoke((MethodInvoker)(() => label2.Text = Convert.ToString(b)));
Thread.Sleep(5000);
b=b+5;
}
}
private void button2_Click(object sender, EventArgs e)
{
if (start_b == false)
{
button2.Text = "Running";
start_b = true;
Thread thread2 = new Thread(new ThreadStart(th2));
thread2.Start();
}
else
{
button2.Text = "Click to start";
start_b = false;
}
}
private void quitting(object sender, FormClosingEventArgs e)
{
start_a = false;
start_b = false;
}
}
}
2993 次
3 に答える
0
終了する他のスレッドと同期する必要があるため、簡単な解決策はありませんが、Invokeは、他のスレッドを閉じることになっているUIスレッドで実行するように要求します。したがって、tUIはt1、t2に終了を要求しますが、t1、t2は終了するためにtUIを必要とする場合があります。:)
次のようなメソッドApplication.DoEvents();
に(読み取り=すべての呼び出し要求を処理する)を追加します。quitting
private void quitting(object sender, FormClosingEventArgs e)
{
start_a = false;
start_b = false;
Application.DoEvents(); // NOT the solution, is not enough!!!
}
ほとんどの競合状態をソートしますが、十分ではありません。
なんで?この可能性はありますが、非常にありそうもない競合状態のため、次のようになります。
t1 before queuing Invoke
~~~~~~~>
start_a = false; start_b= false; Application.DoEvents();
<~~~~~~~
t1 queue an Invoke
~~~~~~~> (very improbable but possible)
(continue trough disposing)
<~~~~~~~
queued Invoke on disposed label -> crash!
開始変数のステータスをチェックするクリティカルセクションをロックし、メッセージキューを空にすることでうまくいくはずです。あなたの運動:他の可能な競合状態を見つけ、最悪の場合5秒より早く終了する方法を見つけてください(ヒント:睡眠を使用しないでください。睡眠は悪魔です)。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
object _closing1;
object _closing2;
volatile bool start_a = false;
volatile bool start_b = false;
public Form1()
{
InitializeComponent();
button1.Text = "Click to start";
button2.Text = "Click to start";
_closing1 = new object();
_closing2 = new object();
}
private void button1_Click(object sender, EventArgs e)
{
if (start_a == false)
{
button1.Text = "Running";
start_a = true;
Thread thread2 = new Thread(new ThreadStart(th1));
thread2.Start();
}
else
{
button1.Text = "Click to start";
start_a = false;
}
}
void th1()
{
int a = 0;
while (true)
{
lock (_closing1)
{
if (start_a == false)
break;
label1.BeginInvoke((MethodInvoker)(() => label1.Text = Convert.ToString(a)));
}
Thread.Sleep(50);
a++;
}
}
void th2()
{
int b = 0;
while (true)
{
lock (_closing2)
{
if (start_b == false)
break;
label2.BeginInvoke((MethodInvoker)(() => label2.Text = Convert.ToString(b)));
}
Thread.Sleep(5000);
b = b + 5;
}
}
private void button2_Click(object sender, EventArgs e)
{
if (start_b == false)
{
button2.Text = "Running";
start_b = true;
Thread thread2 = new Thread(new ThreadStart(th2));
thread2.Start();
}
else
{
button2.Text = "Click to start";
start_b = false;
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
lock (_closing1)
{
start_a = false;
// Clear the message queue now so access on disposed lables is possible.
// No more invokes will be queued because 1) start_a = false
// 2) t1 is out of the critical section
Application.DoEvents();
}
lock (_closing2)
{
start_b = false;
// Clear the message queue now so access on disposed lables is possible.
// No more invokes will be queued because 1) start_b = false
// 2) t2 is out of the critical section
Application.DoEvents();
}
}
}
}
于 2011-07-09T02:33:47.203 に答える