【问题标题】:Return Backgroundworker without RunWorkerCompleted返回没有 RunWorkerCompleted 的 Backgroundworker
【发布时间】:2018-03-16 23:37:32
【问题描述】:

我正在为我的应用程序编写安装。所以我使用 Steps。

所以我有 Step01()Step02 这样的方法来改变 UI。 在Step01Step02 之间,我需要使用Backgroundworker(登录)。

所以我创建了另一个方法private bool CheckLogin(),它的调用方式如下:

ButtonClick 事件:

if(CheckLogin())
{
    Step02();
}
else
{
    MessageBox.Show(ErrorMessage)
}

因为CheckLogin()boolean 我需要返回truefalse。但是在这种方法中我需要使用Backgroundworker(用于加载动画)。

我的CheckLogin()方法:

private bool CheckLogin(string username, string password)
{
    if(globalLoginWorker.IsBusy)
    {
        globalLoginWorker.CancelAsync();
        LoadingButtonCircular.Visibility = Visibility.Collapsed;
        return false;
    }
    else
    {
        List<string> arguments = new List<string>();
        arguments.Add(username);
        arguments.Add(password);
        LoadingButtonCircular.Visibility = Visibility.Visible;
        BackButton.IsEnabled = false;
        globalLoginWorker.RunWorkerAsync(arguments);
    }
}

在这个后台工作人员 (globalLoginWorker) 中,我有一些错误处理(密码错误、用户不存在等) 现在我需要从 Backgroundworker 返回 true 或 false,以便我可以在 CheckLogin() 方法中返回 true 或 false。

类似:

if(globalLoginWorker.RunWorkerAsync(arguments)
    return true;
else
    return false;

因为我不能等待 Backgroundworker 完成。

编辑: 我现在尝试使用异步任务而不是 Backgroundworker。但是使用这种方法,应用程序将冻结。

private async Task<bool> CheckLogin(string username, string password)
{
    Thread.Sleep(5000) //(to test Loading animation / freeze)
    return true;
}

按钮点击事件:

LoadingButtonCircular.Visibility = Visibility.Visible;
if(CheckLogin("test", "test").Result)
    MessageBox.Show("true");
else
    MessageBox.Show("false");
LoadingButtonCircular.Visibility = Visibility.Collapsed;

【问题讨论】:

  • 不要将 backgroundworker 用于 WPF。使用异步/等待
  • @mm8 在 DoWork 我检查数据库中是否存在用户以及密码等是否正确。我使用 BackgroundWorker 在处理时显示加载动画。如果没有 Backgroundworker,应用程序将在处理时冻结。
  • 将代码从 DoWork 事件处理程序移动到任务并等待任务。
  • @mm8 我编辑了我的问题,向你展示我对 Task 方法的问题。
  • 任务不能保证在新线程上运行,所以 Thread.Sleep 可以冻结你的 UI。请改用await Task.Delay(5000);

标签: c# wpf backgroundworker


【解决方案1】:

BackgroundWorker 不返回任何值。它在单独的线程上执行操作,并在后台操作完成时引发RunWorkerCompleted 事件。

您可以在这里做的是将您在DoWork 事件处理程序中的代码移动到Taskawait 这一个,例如:

private async void Button_Click(object sender, RoutedEventArgs e)
{
    if (await CheckLogin())
    {
        Step02();
    }
    else
    {
        MessageBox.Show(ErrorMessage)
    }
}

private async Task<bool> CheckLogin()
{
    return await Task.Run(() =>
    {
        //this code runs on a background thread...
        Thread.Sleep(5000);
        return true;
    });
}

有关 C# 5 中引入的用于大大简化编写异步代码的 async 和 await 关键字的更多信息,请参阅 MSDN:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/。您不再需要使用BackgroundWorker

【讨论】:

  • 太棒了。谢谢。所以BackgroundWorker 已经过时了,现在都在使用异步代码?我将阅读更多相关信息。感谢您提供这些信息。
猜你喜欢
  • 2011-11-29
  • 1970-01-01
  • 2011-02-17
  • 1970-01-01
  • 1970-01-01
  • 2011-08-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多