我使用WPF应用程序和遗留代码。有一种用于分配液体的应用。每次新的剂量应检查杯子是否被分配器更换,如果没有,则显示需要更换杯子的消息。分配器有一个更换杯传感器。如果杯子被更换,我需要自动关闭MessageBox。为此运行两个线程。首先是MessageBox,在另一个调查过程中分配器。这是代码:
public bool CheckChangeCupInThread()
{
if (_dispenser.Status.CupChanged == DispenserEnums.CupChanged.False)
{
var cupFormThread = new ThreadStart(CupWaitChangeForm);
var cupFormWaiter = new Thread(cupFormThread) {IsBackground = true};
cupFormWaiter.SetApartmentState(ApartmentState.STA);
var cupThread = new ThreadStart(WaitForCupChange);
var cupWaiter = new Thread(cupThread) {IsBackground = true};
cupWaiter.SetApartmentState(ApartmentState.STA);
cupFormWaiter.Start();
cupWaiter.Start();
do
{
//Wait for Cup to be changed or Cancel
} while (cupFormWaiter.IsAlive && cupWaiter.IsAlive);
var watch = new Stopwatch();
watch.Start();
if (cupFormWaiter.IsAlive)
{
cupFormWaiter.Abort();
}
if (cupWaiter.IsAlive)
{
_dispenser.SurveillanceWorker.Continue = false;
cupWaiter.Join(200);
return false;
}
watch.Stop();
}
return true;
}
private void WaitForCupChange()
{
do
{
_dispenser.GetStatus();
} while (_dispenser.Status.CupChanged == DispenserEnums.CupChanged.False);
}
private void CupWaitChangeForm()
{
MessageBox.Show("Change please the cup", "Cup сhange", MessageBoxButtons.Cancel);
}
此代码之前已用于具有超过4000行代码的大型类中。我做了重构并将此代码放在一个单独的类中。现在,更换杯子后程序崩溃,不是在这个地方,而是代码中的某个地方。在Windows 10中使用应用程序时经常会发生的最有趣的事情,这在Windows 7中都不会发生。我是多线程的新手并且无法理解,我该如何解决这个问题。我尝试使用任务和令牌,但令牌不能用MessageBox关闭线程,直到按下按钮。感谢
答案 0 :(得分:0)
我解决了一个问题。如果Task1完成,现在MessageBox关闭了。或者我关闭MessageBox,然后终止Task1
internal class Program
{
public const int WM_SYSCOMMAND = 0x0112;
public const int SC_CLOSE = 0xF060;
[DllImport("user32.dll")]
public static extern int FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
private static void Main(string[] args)
{
Action<object> action = (object obj) =>
{
int i = 0;
do
{
Thread.Sleep(500);
i++;
} while (i < 10);
Console.WriteLine("t1 has been finished");
};
Action<object> action1 = (object obj) =>
{
DialogResult result = DialogResult.OK;
do
{
result = MessageBox.Show("This is task2", "Task2", MessageBoxButtons.OKCancel);
} while (result != DialogResult.Cancel);
Console.WriteLine("t2 has been finished");
};
var tasks = new Task[2];
var source1 = new CancellationTokenSource();
var token1 = source1.Token;
Task t1 = new Task(action, "alpha", token1);
tasks[0] = t1;
Task t2 = new Task(action1, "betha");
tasks[1] = t2;
t1.Start();
Console.WriteLine("t1 has been launched. (Main Thread={0})",
Thread.CurrentThread.ManagedThreadId);
t2.Start();
Console.WriteLine("t2 has been launched. (Main Thread={0})",
Thread.CurrentThread.ManagedThreadId);
try
{
int index = Task.WaitAny(tasks);
if (t1.Status == TaskStatus.Running)
source1.Cancel();
if (t2.Status == TaskStatus.Running)
CloseMessage();
Console.WriteLine("Task #{0} completed first.\n", tasks[index].Id);
Console.WriteLine("Status of all tasks:");
foreach (var t in tasks)
Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status);
}
catch (AggregateException)
{
Console.WriteLine("An exception occurred.");
}
Console.ReadLine();
}
private static void CloseMessage()
{
int window = FindWindow(null, "Task2");
if (window != 0)
SendMessage(window, WM_SYSCOMMAND, SC_CLOSE, 0);
}
}