There is a WPF application, used for dispensing liquids. With each new dosing, it is necessary to check whether the capacity under the dosing unit has changed, and if not, display a message about the need to change the capacity. There is such a code

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(); cupFormWaiter.Join(); } 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); } 

here _dispenser itself is the dispenser. The principle is this: either the capacitance is changed, or the Cancel button in the MessageBox is pressed, the threads end with the corresponding result. Everything seems normal at first glance. But very often this code causes the program to crash. I tried to do the same with tasks, but somehow it didn’t work out well, I’m new to multithreaded applications. I work with WPF and MVVM pattern.

  • And the question is what? - Anton Papin
  • Do you want to redo the code using Task ? Or what? - Bulson
  • The question is how to get rid of this program crash. I do not know how best with Tasky, or without. I have a problem with the fact that the program crashes - S_Schmal
  • Show your error, the given code does not have to generate exceptions, you need to understand. - Anton Papin
  • one
    What SetApartmentState tin ... Why two threads, SetApartmentState , empty loop, re-check on IsAlive ? - Raider

1 answer 1

Found a solution to your problem. Now the MessageBox is closed if Task1 ends, or Task1 is interrupted, if the Cancel button is pressed in the MessageBox

 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); } }