【问题标题】:RunWorkerCompleted is not firing when triggered from FormClosing从 FormClosing 触发时,RunWorkerCompleted 未触发
【发布时间】:2013-04-10 19:10:41
【问题描述】:

我有一个表单需要通过 Web 服务调用将未保存的数据保存到外部数据库。当用户手动保存数据时,会触发 RunWorkerCompleted,但是当我通过 FormClosing 事件调用该方法时不会触发。

在用户修改表单中的值几秒钟后计时器会计时,如果用户修改另一个值,则计时器会重置,其想法是“toSend”列表有多个值,我可以发布多个更改一次,因为 Web 服务调用开销很大。

    private void timer1_Tick(object sender, EventArgs e)
    {
        if (PublishBackgroundWorker.IsBusy)
            return;

        List<object> toSend = new List<object>();

        // Figure out what changed and add it to toSend ...
        toSend.Add(changedItems);

        if (toSend.Count >= 1)
            PublishBackgroundWorker.RunWorkerAsync(toSend);
    }

    private void PublishBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        if (((List<object>)(e.Argument)).Count > 0)
        {
            Service.SrvObjects[] ret = Svc.PublishItems(e.Argument));
        }
    }

    private void PublishBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Invoke(new UpdateStatusCallback(this.UpdateStatus), new object[] { "Ready" });
    }

    private void IPTUserInterfaceForm_FormClosing(object sender, FormClosingEventArgs e)
    {
        timer1.Enabled = false;
        timer1_Tick(this, new EventArgs());
        //Application.DoEvents();
        while (PublishBackgroundWorker.IsBusy)
            System.Threading.Thread.Sleep(100);
    }

这有意义吗?当用户更改值并在计时器关闭之前关闭表单时,我手动 Tick 希望 PublishBackgroundWorker.IsBusy 在某些时候为假,这永远不会是因为从未调用过 RunWorkerCompleted。

【问题讨论】:

  • 我看不出你为什么会从PublishBackgroundWorker_RunWorkerCompleted 中调用Invoke
  • 它只是向用户更新,发布到服务器已完成。由于它在一个单独的线程上,我需要一个委托来更新表单上的文本.... public delegate void UpdateStatusCallback(string text);私人无效UpdateStatus(字符串文本){StatusStripLabel.Text = text; System.Threading.Thread.Sleep(5); }
  • 第一直觉:这听起来像你错过了一个Application.DoEvents 电话。另见here

标签: c# forms timer backgroundworker formclosing


【解决方案1】:

问题在于,您的 Backgroundworker 并不因为您调用 timerTick 方法而忙碌。因此,在方法的其余部分运行并关闭表单并关闭应用程序之前,永远不会到达此代码:

    while (PublishBackgroundWorker.IsBusy)
        System.Threading.Thread.Sleep(100);

【讨论】:

  • 但是在Timer_Tick中调用了后台worker RunWorkerAsync,不会触发worker运行,所以DoWork完成后需要该线程调用RunWorkerCompleted?
  • 尝试将Thread.Sleep(100); 放在代码中//Application.DoEvents(); 的位置...我猜这是竞争条件。
  • 知道了...如果我将 Application.DoEvents 与 Sleep 一起放在 while 循环中,它就可以工作。我知道了。谢谢!
猜你喜欢
  • 1970-01-01
  • 2011-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多