首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >winforms线程未停止winforms c#

winforms线程未停止winforms c#
EN

Stack Overflow用户
提问于 2011-12-18 08:45:38
回答 2查看 1.4K关注 0票数 2

我正在使用MSMQ线程调用一个小的例程,它接收来自BackgroundWorker的消息,只要消息到达MSMQ队列(每隔5秒消息到达MSMQ ),它就会到达我使用BackgroundWorker线程的应用程序。下面是我的Win窗体类。我是线程新手,所以如果我做错了什么,请道歉

问题:我的应用程序是MDI应用程序,当我第一次执行我的应用程序时,它工作得很好,并在它到达队列时立即接收MSMQ消息,这是每隔5秒,但当我关闭这个窗体时,它关闭得很好,但在打开这个相同的窗体后,我收到了来自MSMQ的消息,延迟了10秒,所以这意味着我在后台工作线程中搞乱了什么,我试图取消这个后台工作线程,但我失败了,无法正确地扫描或终止线程。请帮助并分享您的经验。下面是我的表单代码。

代码语言:javascript
复制
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();

    }
}
EN

回答 2

Stack Overflow用户

发布于 2011-12-18 09:31:52

这里有两个选项:

1)在窗体的关闭事件中,调用backgroundWorker1.CancelAsync()。

2)更好的方法是完全移除后台工作线程,并使用MessageQueue的本地异步处理机制。您可以在添加ReceivedCompleted事件处理程序之后使用BeginReceive方法启动队列请求,然后在已完成的事件处理程序中处理消息并重新启动请求。

问题是,如果您发出接收请求,它将阻塞后台工作线程,直到在队列中收到消息为止,而CancelAsync只会请求停止后台工作线程,而不会取消接收请求。

例如(更新):

代码语言:javascript
复制
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));
        }
    }

}
票数 1
EN

Stack Overflow用户

发布于 2011-12-18 09:22:59

当您关闭窗体时,是否终止工作进程?如果没有,是否存在对窗体或工作程序的引用(事件处理程序?)那么它将不会获得GCd并继续存在。在打开第二个实例时,您可能有两个后台工作进程正在运行...

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8549050

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档