C# 从窗体关闭触发时,RunWorkerCompleted未触发

C# 从窗体关闭触发时,RunWorkerCompleted未触发,c#,forms,timer,backgroundworker,formclosing,C#,Forms,Timer,Backgroundworker,Formclosing,我有一个表单需要通过web服务调用将未保存的数据保存到外部DB。当用户手动保存数据时,会触发RunWorkerCompleted,但在我通过FormClosing事件调用该方法时不会触发 在用户修改表单中的一个值后,计时器会在几秒钟后滴答作响,如果用户修改了另一个值,计时器就会重置,因为“toSend”列表有多个值,而且我可以一次发布多个更改,因为web服务调用会带来大量开销 private void timer1_Tick(object sender, EventArgs e)

我有一个表单需要通过web服务调用将未保存的数据保存到外部DB。当用户手动保存数据时,会触发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);
    }
private void timer1\u勾选(对象发送方,事件参数e)
{
if(PublishBackgroundWorker.IsBusy)
返回;
List toSend=新列表();
//找出更改的内容并将其添加到toSend。。。
toSend.Add(changedItems);
如果(toSend.Count>=1)
PublishBackgroundWorker.RunWorkerAsync(toSend);
}
私有void PublishBackgroundWorker_DoWork(对象发送方,DoWorkEventArgs e)
{
如果(((列表)(如参数)).Count>0)
{
Service.SrvObjects[]ret=Svc.PublishItems(e.Argument));
}
}
private void PublishBackgroundWorker_RunWorkerCompleted(对象发送方,RunWorkerCompletedEventArgs e)
{
调用(newupdatestatuscallback(this.UpdateStatus),新对象[]{“Ready”});
}
私有void IPTUserInterfaceForm_FormClosing(对象发送方,FormClosingEventArgs e)
{
timer1.Enabled=false;
timer1_勾选(这是新的EventArgs());
//Application.DoEvents();
while(PublishBackgroundWorker.IsBusy)
系统线程线程睡眠(100);
}

这有意义吗?当用户更改一个值,并在计时器关闭之前关闭表单时,我手动勾选PublishBackgroundWorker.IsBusy在某个点上为false,这绝不是因为从未调用RunWorkerCompleted。

问题是,您的Backgroundworker不忙,只是因为您调用了timerTick方法。因此,在方法的其余部分运行完毕、表单关闭以及应用程序关闭之前,永远不会到达此代码:

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

我看不出你为什么要从
PublishBackgroundWorker\u runworker completed
中调用
Invoke
。这只是向用户更新到服务器的发布已完成。由于它在一个单独的线程上,我需要一个代理来更新表单上的文本。。。。公共委托void UpdateStatusCallback(字符串文本);private void UpdateStatus(string text){StatusStripLabel.text=text;System.Threading.Thread.Sleep(5);}第一反应:听起来好像您错过了一个调用。另请参见,但后台工作线程RunWorkerAsync在Timer_Tick中被调用,这不会触发工作线程运行,因此该线程需要在DoWork完成后调用RunWorkerCompleted?请尝试放置一个
thread.Sleep(100)代码中有
//Application.DoEvents()的地方。。。我想这是比赛条件,明白了。。。如果我将
应用程序.DoEvents
与Sleep放在while循环中,它就会工作。我明白了。谢谢