5

我是使用事件处理程序和后台工作程序的新手,所以我可能在这里遗漏了一些完全明显的东西。尽管如此,我已经尝试解决这个问题两天了,所以我想我不妨看看有人要说什么。

我有一个名为 SqlExpressDownloader 的后台工作人员。它在我的程序开始时开始运行,其余的工作运行,然后它应该等待SqlExpressDownloader_DoWork()方法中的操作完成才能继续。唯一的问题是,出于某种原因,每当我这样做时while(SqlExpressDownloader.IsBusy),它总是响应忙,因此会永远等待。

事件处理程序的代码在这里:

    private void SqlExpressDownloader_DoWork(object sender, DoWorkEventArgs e)
    {
        string sSource = string.Format("{0}\\{1}", Paths.Settings_Common, "sqlexpr_x64_enu.exe");
        Debug.WriteLine(sSource);
        Debug.WriteLine("http://www.elexioamp.com/Install/redistributables/sql2008r2express/sqlexpr_x64_enu.exe");
        if (!System.IO.File.Exists(sSource))
        {
            WebClient oWebClient = new WebClient();
            oWebClient.DownloadProgressChanged += DownloadProgressChanged;
            oWebClient.DownloadDataCompleted += DownloadComplete;

            oWebClient.DownloadFileAsync(new System.Uri("http://www.elexioamp.com/Install/redistributables/sql2008r2express/sqlexpr_x64_enu.exe"), sSource);

            while (oWebClient.IsBusy)
            {
                Thread.Sleep(100);
            }

            e.Result = "";
            DownloadFinished = true;
        }
    }

我已经看过代码并且已经看过它完成了这个方法。我什至在return之后添加了一个DownloadFinished = true,但它仍然响应为忙。我想知道的是如何让后台工作人员响应不忙。

编辑所有事件都添加到构造函数中,如下所示:

        SqlExpressDownloader = new BackgroundWorker();
        SqlExpressDownloader.DoWork += new DoWorkEventHandler(this.SqlExpressDownloader_DoWork);
        SqlExpressDownloader.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.SqlExpressDownloader_RunWorkerCompleted);

RunWorkerCompleteEventHandler看起来像这样:

    private void SqlExpressDownloader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error != null)
        {
            Debug.WriteLine("The actions are complete.");
        }
        else
        {
            Debug.WriteLine("Error in completed work.");
        }
    }

但是,当我上次调试它时,它实际上并没有触发。

4

3 回答 3

3

不要在循环中查询,而是SqlExpressDownloader.IsBusy尝试订阅RunWorkerCompleted事件BackgroundWorker并将您的代码放在那里,该代码只应在DoWork事件完成后发生。

您还可以访问RunWorkerCompletedEventArgs,您可以检查以确保DoWork您的BackgroundWorker.

    ...
    ...
    SqlExpressDownloader.RunWorkerCompleted += SqlExpressDownloader_RunWorkerCompleted;
    SqlExpressDownloader.RunWorkerAsync();
}

private void SqlExpressDownloader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error != null)
    {
        // do something in response to the error
    }

    // stuff to do after DoWork has completed
}

当我学习如何使用这些时,我发现Joe Albahari 的教程很有帮助。

于 2013-07-11T14:52:26.117 回答
1

You can replace your code with more elegant async/await solution like this

private async Task SqlExpressDownloadAsync()
{
    string sSource = string.Format("{0}\\{1}", Paths.Settings_Common, "sqlexpr_x64_enu.exe");
    Debug.WriteLine(sSource);
    Debug.WriteLine("http://www.elexioamp.com/Install/redistributables/sql2008r2express/sqlexpr_x64_enu.exe");
    if (!System.IO.File.Exists(sSource))
    {
        WebClient oWebClient = new WebClient();
        oWebClient.DownloadProgressChanged += DownloadProgressChanged;
        oWebClient.DownloadDataCompleted += DownloadComplete;
        await oWebClient.DownloadFileTaskAsync(new System.Uri("http://www.elexioamp.com/Install/redistributables/sql2008r2express/sqlexpr_x64_enu.exe"), sSource);  
    }   
}
于 2013-07-11T14:49:56.310 回答
1

我有一个类似的问题。DownloadASync 会触发,但 .IsBusy 将始终保持为真。

这可能不是一个常见的问题,只是想我分享我的解决方案。

我用了

MessageBox.Show(new Form() { TopMost = true }, "", "")

这就是原因。我也试过:

var t = new Form() { TopMost = true };
MessageBox.Show(t, "", "");
t.Dispose();

这导致了同样的问题。

我的代码有多个线程,我假设其中一个线程一定被卡住了,或者 MessageBox(the new Form() { TopMost = true; } ) 调用创建了一个卡住的线程。

一旦我删除了那部分,例如。

MessageBox.Show("", "");

一切都再次按预期工作。

所以也许你正在某个地方创建另一个导致你的问题的线程。

于 2015-06-12T14:14:45.020 回答