2017-02-24 4 views
-1

私はWPFアプリケーションと従来のコードを使用しています。液体を分配するために使用される用途がある。カップがディスペンサーに交換されたかどうかを確認する必要があります。そうでない場合は、カップを交換する必要があるというメッセージを表示します。ディスペンサーにはチェンジカップセンサーがあります。カップが変更された場合、私は近くに自動的にMessageBoxが必要です。これは2つのスレッドを実行します。最初は別の調査プロセスディスペンサの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

私は2つのスレッドが必要だと思います。なぜなら、2つのイベントがあるか、カップが変更されているか、MessageBoxのボタン「キャンセル」がクリックされているからです。私はどのように両方を見ますか? – SergS

+0

追加のスレッドは必要ありません。あなたはコードを非同期にするように構造化するべきであり、生産性の高いものの代わりにCPU上に卵を調理するループの中に座っているのではなく、変更を通知されるべきです。 – Servy

答えて

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); 
    } 
} 
関連する問題