2011-12-18 12 views
2

BackgroundWorkerスレッドを使用して、メッセージがMSMQキューに到着するとすぐにMSMQからメッセージを受信します(メッセージは5秒ごとにmsmqに送られます)。これはスレッドBackgroundWorkerを使用しています。以下は私のWin Formクラスです。私はスレッドに新しいですので、私が何か間違っている場合はappologyをしてくださいBackgroundWorkerスレッドがwinformsを停止していません。C#

問題:私のアプリケーションはMDIアプリケーションです。初めてアプリケーションを実行しているときに完全にうまく動作し、すぐにMSMQメッセージを受信します。キューは5秒ごとですが、このフォームを閉じると子フォームになりますが、この同じフォームを開いた直後にMSMQからダーレイの10秒間のメッセージを受信して​​いるので、何かを台無しにしていますバックグラウンドワーカースレッドでこのバックグラウンドワーカースレッドを取り消そうとしましたが、失敗してスレッドを正常に終了または終了できませんでした。助けてあなたの経験を共有してください。以下は私のフォームコードです。

public partial class FrmBooking : BookingManager.Core.BaseForm.BaseForm 
{ 
    internal const string queName = @"messageServer\private$\Response"; 
    private Int32 counter = 0; 
    BackgroundWorker backgroundWorker1 = new BackgroundWorker(); 


    public FrmBooking() 
    { 
     InitializeComponent(); 
     backgroundWorker1.WorkerReportsProgress = true; 
     backgroundWorker1.WorkerSupportsCancellation = true; 
     backgroundWorker1.RunWorkerCompleted+=new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted); 
     backgroundWorker1.ProgressChanged+=new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged); 
     backgroundWorker1.DoWork+=new DoWorkEventHandler(backgroundWorker1_DoWork); 

    }   

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     BackgroundWorker bgWorker = sender as BackgroundWorker; 

     if (bgWorker.CancellationPending) 
     { 
      e.Cancel = true; 
      return; 
     } 


      try 
      { 

       MessageQueue messageQueue = null; 
       if (MessageQueue.Exists(queName)) 
       { 
        messageQueue = new MessageQueue(queName); 
       } 
       else 
       { 
        MessageQueue.Create(queName); 
       } 

       messageQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(String) }); 

       System.Messaging.Message msg = messageQueue.Receive(); 



       bgWorker.ReportProgress(100, msg); 

      } 
      catch (Exception ex) { } 


    } 
    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     if (!e.Cancelled) 
     { 
      backgroundWorker1.RunWorkerAsync(); 
     } 


    } 
    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 

     System.Messaging.Message msg = e.UserState as System.Messaging.Message; 

     listBoxControl1.Items.Add(msg.Body.ToString()); 
     counter++; 
     labelControl1.Text = String.Format("Total messages received {0}", counter.ToString()); 
    } 

    private void FrmBooking_Load(object sender, EventArgs e) 
    { 
     backgroundWorker1.RunWorkerAsync(); 

    } 
} 

答えて

0

フォームを閉じると、ワーカーを終了しますか?もしそうでなければ、フォームへの参照やどこかのワーカー(イベントハンドラ?)への参照があれば、GCdを取得せずに残ります。あなたは2人の背景の労働者が実行している可能性が2つ目のインスタンスを開くと....

+0

はい、私は)(backgroundworker.cancelasyncを言ってみましたが、これは助けdoestフォームを閉じています。あなたは正しいですそれは参照がいくつか生きている、どのように私はそれを停止することができます...まだ努力しているかわからない – Shax

1

あなたはここに2つのオプションがあります。

1)フォームのClosingイベントで、backgroundWorker1を呼び出します。 CancelAsync()。

2)より良いアプローチは、バックグラウンドワーカーを完全に削除し、MessageQueueのネイティブ非同期処理メカニズムを使用することです。 ReceivedCompletedイベントハンドラを追加した後にBeginReceiveメソッドを使用してキュー要求を開始し、完了したイベントハンドラでメッセージを処理して要求を再開できます。

問題は、受信要求を発行すると、キューにメッセージが受信されるまでバックグラウンドワーカースレッドがブロックされ、CancelAsyncはバックグラウンドワーカーに停止を要求するだけで、Receive要求。例えば

(更新):

public partial class FrmBooking : BookingManager.Core.BaseForm.BaseForm 
{ 
    public FrmBooking() 
    { 
     InitializeComponent(); 

     this.FormClosing += new FormClosingEventHandler(FrmBooking_FormClosing); 
    } 

    internal const string queName = @"messageServer\private$\Response"; 
    private Int32 counter = 0; 
    private MessageQueue messageQueue = null; 

    private bool formIsClosed = false; 

    private void FrmBooking_Load(object sender, EventArgs e) 
    { 
     StartQueue(); 
    } 

    void FrmBooking_FormClosing(object sender, FormClosingEventArgs e) 
    { 
     // Set the flag to indicate the form is closed 
     formIsClosed = true; 

     // If the messagequeue exists, close it 
     if (messageQueue != null) 
     { 
      messageQueue.Close(); 
     } 
    } 

    private void StartQueue() 
    { 
     if (MessageQueue.Exists(queName)) 
     { 
      messageQueue = new MessageQueue(queName); 
     } 
     else 
     { 
      MessageQueue.Create(queName); 
     } 

     messageQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(String) }); 

     // Add an event handler for the ReceiveCompleted event. 
     messageQueue.ReceiveCompleted += new ReceiveCompletedEventHandler(MessageReceived); 

     messageQueue.BeginReceive(TimeSpan.FromSeconds(15)); 
    } 

    // Provides an event handler for the ReceiveCompleted event. 
    private void MessageReceived(Object source, ReceiveCompletedEventArgs asyncResult) 
    { 
     if (!this.formIsClosed) 
     { 
      // End the asynchronous receive operation. 
      System.Messaging.Message msg = messageQueue.EndReceive(asyncResult.AsyncResult); 

      // Display the message information on the screen. 
      listBoxControl1.Items.Add(msg.Body.ToString()); 
      counter++; 
      labelControl1.Text = String.Format("Total messages received {0}", counter.ToString()); 

      // Start receiving the next message 
      messageQueue.BeginReceive(TimeSpan.FromSeconds(15)); 
     } 
    } 

} 
+0

はい、それは私がすでにCancelAsync()と呼ばれていたが、助けていないthats。他のアイデア?私はtimespanを使うことができると知っていますが、私はtimespanによっていくつかのメッセージを遅く読むかもしれないので、使いたくありません。だから私はそれがキューに入ると、メッセージを読む必要があります。 – Shax

+0

@ Shax:新しいメッセージがキューに受信されるまで、現在の実装がbackgroundworkerスレッドをハングアップするので、上記の方法2を使用するようにコードを書き直すことをお勧めします。 –

+0

2番目の方法も試しましたが、同じ応答です。実装するコードを共有できますか? – Shax

関連する問題