我正在使用MSMQ线程调用一个小的例程,它接收来自BackgroundWorker的消息,只要消息到达MSMQ队列(每隔5秒消息到达MSMQ ),它就会到达我使用BackgroundWorker线程的应用程序。下面是我的Win窗体类。我是线程新手,所以如果我做错了什么,请道歉
问题:我的应用程序是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();
}
}发布于 2011-12-18 09:31:52
这里有两个选项:
1)在窗体的关闭事件中,调用backgroundWorker1.CancelAsync()。
2)更好的方法是完全移除后台工作线程,并使用MessageQueue的本地异步处理机制。您可以在添加ReceivedCompleted事件处理程序之后使用BeginReceive方法启动队列请求,然后在已完成的事件处理程序中处理消息并重新启动请求。
问题是,如果您发出接收请求,它将阻塞后台工作线程,直到在队列中收到消息为止,而CancelAsync只会请求停止后台工作线程,而不会取消接收请求。
例如(更新):
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));
}
}
}发布于 2011-12-18 09:22:59
当您关闭窗体时,是否终止工作进程?如果没有,是否存在对窗体或工作程序的引用(事件处理程序?)那么它将不会获得GCd并继续存在。在打开第二个实例时,您可能有两个后台工作进程正在运行...
https://stackoverflow.com/questions/8549050
复制相似问题