2

我正在尝试在登录时启用繁忙指示器。我遇到的问题是,在所有操作完成之前它不会启用。我如何在登录后立即告诉线程更新 UI 以尽快启动指示器?

    private void LoginButton_Click(object sender, RoutedEventArgs e)
    {
        this.Dispatcher.Invoke((Action)(() =>
        {
            radBusyIndicator.IsBusy = true;
            //var backgroundWorker = new System.ComponentModel.BackgroundWorker();
            //backgroundWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(backgroundWorker_DoWork);
            //backgroundWorker.RunWorkerAsync();
        }));

        string error = string.Empty;
        long userId = 0;

        //Login code here....
        //...........  bunch of other code. etc..

     }
4

2 回答 2

9

一旦 UI 线程空闲,UI 就会更新。在这种情况下不需要Dispatcher.Invoke,因为您已经在 UI 线程中。

这里的关键是将“工作”移动到后台线程中,即:

private void LoginButton_Click(object sender, RoutedEventArgs e)
{
    radBusyIndicator.IsBusy = true;
    LoginButton.IsEnabled = false; // Prevent clicking twice

    string error = string.Empty;
    long userId = 0;

    // Start this in the background
    var task = Task.Factory.StartNew(()=>
    {
        //Login code here....
        //...........  bunch of other code. etc..
    });

    // Run, on the UI thread, cleanup code afterwards
    task.ContinueWith(t =>
    {
        // TODO: Handle exceptions by checking t.Exception or similar...

        radBusyIndicator.IsBusy = false;
        LoginButton.IsEnabled = true;
    }, TaskScheduler.FromCurrentSynchronizationContext());
 }

如果您使用的是 C# 5,则可以通过使登录和其他代码异步来简化此操作:

private async void LoginButton_Click(object sender, RoutedEventArgs e)
{
    radBusyIndicator.IsBusy = true;
    LoginButton.IsEnabled = false; // Prevent clicking twice

    long userId = 0;

    // Call async method with await, etc...
    string error = await DoLoginAsync(userId);

    var result = await BunchOfOtherCodeAsync();

    radBusyIndicator.IsBusy = false;
    LoginButton.IsEnabled = true;
 }
于 2013-06-27T20:58:33.470 回答
0

您可以使用 BAckground Worker Thread 并将其两个 eventHandlers 订阅到您想要处理的事件中......例如-

BackgroundWorker Worker=new BackgroundWorker();
worker.DoWork+=Yorevent which will do the timeTaking Task();
Worker.RunWorkerCompleted+=YOurEvent which will Update your UI after the work is done();
worker.RunWorkerAsync();

这样它也不会导致任何线程错误..

只需在 TimeTaking 任务开始时启用您的 BusyIndi​​cator,当 timeTaking 任务完成时,只需在 RUNWorkerCompleted 事件中禁用您的 Busy Indicator。

于 2013-06-29T10:50:44.027 回答