为了账号安全,请及时绑定邮箱和手机立即绑定

GUI 在单击之前不响应

GUI 在单击之前不响应

C#
九州编程 2022-01-09 15:09:25
我有一个与这里类似的问题:WPF MVVM Light: Command.RaiseCanExecuteChanged() doesn't work,使用带有 WPF 的命令并且我的 GUI 无法工作,直到我单击屏幕中的某个位置。我不使用 MVVM Light。我通过调用 ExternalDLL.Start() 调用外部 DLL 来执行某些操作,然后调用 GetStatus() 以了解操作是否已开始。如果我得到正确的状态作为回报,我改变了实际的行动,它必须激活我的 GUI 上的一个按钮。在我单击某个地方之前,该按钮不会自行激活。我检查了线程,但它似乎在同一个线程上,我试图将它放在 GUI 线程中,通过使用Application.Current.Dispatcher.BeginInvoke,但它也不起作用。这是我的代码:private async void StartScanCommand_Executed(object sender, ExecutedRoutedEventArgs e){      ExternalDLL.Start();      WaitForStarting();}private async void WaitForStarting(){    Waiting();    Stopwatch chrono = new Stopwatch();    chrono.Start();    bool started = false;    while (chrono.ElapsedMilliseconds < 20000)    {        if (ExternalDLL.GetStatus() != ExternalDLL.Status.Started)        {            await Task.Delay(100);        }        else        {            started = true;            chrono.Stop();            StartedAction();            break;        }    }    if (!started)    {        MessageBox.Show("Error");    }}该Waiting()方法调用激活GUI和工作的按钮。但是StartedAction()也必须激活一个按钮,并且不起作用。这是开始操作的代码:private void StartedAction(){    _actualAction = ActualAction.DoingAction;}这是按钮的可以执行方法:private void SomeButtonCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) {     e.CanExecute = _actualAction == ActualAction.DoingAction; }我究竟做错了什么 ?
查看完整描述

2 回答

?
牛魔王的故事

TA贡献1830条经验 获得超3个赞

问题很简单,当ActualAction值更改时,绑定命令的 CanExecute 状态不会重新评估。


要求CommandManager.InvalidateRequerySuggested()强制重新评估。


private void StartedAction()

{

    _actualAction = ActualAction.DoingAction;

    CommandManager.InvalidateRequerySuggested();

}


查看完整回答
反对 回复 2022-01-09
?
潇潇雨雨

TA贡献1833条经验 获得超4个赞

您正在 UI 线程上进行后台工作。不要在那里做,在另一个线程中做,并使用轮询、事件或其他回调方法来更新 UI(在 UI 线程上)。


例如,您可以这样做:


Task.Run(() => { OtherDll.DoWork(); };

这将启动外螺纹上的其他工作。


如果您需要更多控制,您可以将其他 dll 的功能单独包装在一个线程中。


Public Class OtherDLLThread 

{

    Thread _internalThread;


    public OtherDLLThread()

    {

         _internalThread = new Thread(ThreadMainLoop);

    }


    public void ThreadMainLoop()

    {

        OtherDLL.DoWork();

    }


    public static void Start() 

    {

       _internalThread.Start();

    }


}

像这样使用它:


OtherDLLThread other = new OtherDLLThread();

other.Start();

这是另一个将代码插入 UI 线程的函数:


    /// <summary>

    ///     Runs the action on UI thread.

    /// </summary>

    /// <param name="action">The action.</param>

    public static void RunOnUIThread(Action action)

    {

        try

        {

            if (Application.Current != null)

                Application.Current.Dispatcher.Invoke(action);

        }

        catch (Exception ee)

        {

            _logger.Fatal("UI Thread Code Crashed. Action detail: " + action.Method, ee);

            //SystemManager.Instance.SendErrorEmailToCsaTeam("Kiosk Application Crashed", "UI Thread Code Crashed. Action detail: " + action.Method);

            throw;

        }

    }

像这样使用它:


RunOnUITHread(() => lblStatus.Text = "Working...");


查看完整回答
反对 回复 2022-01-09
  • 2 回答
  • 0 关注
  • 252 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信