C# 需要等待线程完成而不阻塞 UI 线程

我在 UI 线程上显示 ProgressBar,然后在另一个线程上启动登录过程。这完美地工作,我得到了 ProgressBar “圆圈”,它让用户知道正在发生的事情。问题是我需要通过 UI 向用户返回任何登录错误,例如无效的用户名/密码。我更改了我的 ProgressBar 类以包含一个ErrorMessage属性,将其实例化并将其作为参数传递给登录过程。如果出现任何错误,我都会设置该ErrorMessage属性。如果它不为空,我将显示错误。if问题是登录线程在我到达检查 null之前没有完成。这都是在按钮单击事件上完成的。我的代码:


MyButton_Submit.Click += async (sender, e) =>

{

        ManualResetEvent resetEvent = new ManualResetEvent(false);

        ProgressBarHandler myprogressbar = new ProgressBarHandler(this);

        myprogressbar.show();


        var thread = new System.Threading.Thread(new ThreadStart(async delegate

        {

            await SignOn(myprogressbar);

            resetEvent.Set();

        }));

        thread.Start();

        // based on @Giorgi Chkhikvadze comment below I changed: resetEvent.WaitOne(); to:


        await Task.Run(() => resetEvent.WaitOne());

        // works perfectly 



        while (thread.ThreadState == ThreadState.Running)

        {

            await Task.Delay(100);

        }

        myprogressbar.hide();


        if (myprogressbar.ErrorMesage != null)

        {

            Context context = Application.Context;

            string text = myprogressbar.ErrorMesage ;

            ToastLength duration = ToastLength.Short;

            var toast = Toast.MakeText(context, text, duration);

            toast.Show();

        }

    };

}

该行resetEvent.WaitOne();显然阻塞了用户界面,因为当我将其注释掉时,会显示进度条,而当我执行它时,它不会。我怎样才能解决这个问题?


繁花不似锦
浏览 264回答 2
2回答

摇曳的蔷薇

您不需要单独的线程;await会自己工作得很好。您也不需要ManualResetEvent将工作完成作为“信号”;使用awaiton aTask效果很好。等效的简化代码:MyButton_Submit.Click += async (sender, e) =>{  ProgressBarHandler myprogressbar = new ProgressBarHandler(this);  myprogressbar.show();  await SignOn(myprogressbar);  myprogressbar.hide();  if (myprogressbar.ErrorMesage != null)  {    ...  }};你永远不Thread应该在 Xamarin 应用程序中输入类型。总有更简单、更好的方法。该Thread类型一般是“强黄色”标志,但在 Xamarin 中是红色标志。

森林海

awaitTask.Run(() => resetEvent.WaitOne());应该可以解决问题。ManualResetEvent不可等待,不能直接在其上使用 await 关键字,因此您需要将其包装在任务中
打开App,查看更多内容
随时随地看视频慕课网APP