2017-02-24 115 views
-1

我使用WPF應用程序和舊代碼。有一個用於分配液體的應用程序。在檢查杯子是否被飲水機替換時,應檢查每次新的飲水量,如果沒有,則顯示需要更換杯子的消息。分配器有一個更換杯子傳感器。如果杯子被改變,我需要自動關閉MessageBox。爲此運行兩個線程。首先是另一個調查過程分配器中的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

有一個在創造另一個線程,如果你只是將有另一個線程就是在一個循環周圍旋轉,直到它做沒有任何意義。只需在原始線程中完成工作即可。 – Servy

+0

我想我需要兩個線程,因爲我有兩個事件 - 或者一個杯子被改變,或者MessageBox中的按鈕「取消」被點擊。我怎麼看兩個? – SergS

+0

你不需要任何額外的線程。你應該構建你的代碼,使它是異步的,並且你會得到一個變化的通知,而不是坐在一個循環中,在你的CPU上製作一個蛋,而不是用它來生產。 – Servy

回答

0

我解決了一個問題。現在MessageBox關閉,如果Task1完成。或者我關閉消息框,然後終止任務1

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