C# 长流程、绑定更新和UI冻结

C# 长流程、绑定更新和UI冻结,c#,wpf,binding,dispatcher,C#,Wpf,Binding,Dispatcher,我的WPF/C#程序使用在特定序列中调用的不同方法。 每个方法都绑定到UI,经过长时间的处理后显示一些数据。 我正在使用调度程序,因为调用的方法位于另一个线程中。 我还希望在不冻结UI的情况下执行此过程,例如,能够取消该过程并自由替换窗口 我的问题是,用户界面根本没有更新(进度条、计算步骤),取消按钮在计算结束之前不会运行。 事实上,即使挂起的长流程没有完成,也不知道如何立即取消常规序列 我不是100%确定使用正确的方法,有没有人有更好的解决方案或建议 前 public void calcula

我的WPF/C#程序使用在特定序列中调用的不同方法。 每个方法都绑定到UI,经过长时间的处理后显示一些数据。 我正在使用调度程序,因为调用的方法位于另一个线程中。 我还希望在不冻结UI的情况下执行此过程,例如,能够取消该过程并自由替换窗口

我的问题是,用户界面根本没有更新(进度条、计算步骤),取消按钮在计算结束之前不会运行。 事实上,即使挂起的长流程没有完成,也不知道如何立即取消常规序列

我不是100%确定使用正确的方法,有没有人有更好的解决方案或建议

public void calculation命令()
{
var bkw=新的BackgroundWorker()
bkw.DoWork+=工作;
bkw.RunWorkerAsync(Dispatcher.CurrentDispatcher);
}
公共作废工作(对象发送者、DoWorkEventArgs e)
{
var dispatcher=e.作为调度程序的参数;
var dispatcherPriority=dispatcherPriority.Background;
行动;
动作=()=>
{
更新(状态信息待定);
};
dispatcher.BeginInvoke(操作,dispatcherPriority);
ViewModel1 ViewModel1=null;
动作=()=>
{
UpdateProgress(10,“抽样计算”);
viewModel1=Application.GetEchantillonnage();//长进程
};
dispatcher.BeginInvoke(操作,dispatcherPriority);
列表长度列表=null;
动作=()=>
{
UpdateProgress(20,“长度计算”);
lengthList=AlgorithmLibrary.LengthCalculations(viewModel1);//长进程
};
dispatcher.BeginInvoke(操作,dispatcherPriority);
ViewModel2 ViewModel2=null;
动作=()=>
{
UpdateProgress(30,“发动机计算”);
viewModel2=Application.GetEngine();//长进程
AlgorithmLibrary.EngineCalculations(viewModel2);//长过程
var FilteredLength=AlgorithmLibrary.LengthFilter(lengthList);//长进程
};dispatcher.BeginInvoke(操作,dispatcherPriority);
///…执行的其他操作将进度值增加到100%
动作=()=>
{
UpdateStatut(StatutsInformation.Finished);
};
dispatcher.BeginInvoke(操作,dispatcherPriority);
}
私人无效信息更新(状态信息状态信息)
{
ViewModelLoading.StationFormation=StationFormation;
}
私有void UpdateProgress(int值,字符串标签)
{
ViewModelLoading.Progress=值;
ViewModelLoading.Step=标签;
}

感谢

在方法
工作中
您正在后台线程上执行。每次调用
dispatcher.BeginInvoke
时,传递给此方法的操作将在UI线程上执行。看到你现在在做什么了吗?请再次查看此代码

// Here, we are on a background thread
action = () =>
{
    // This action is NOT executing yet!  We are just defining it.
    UpdateProgress(10, "Sampling calculations");
    // This is going to execute on the thread that executes this action!
    viewModel1 = Application.GetEchantillonnage();//Long process
};
// here, we are still on the background thread, but we are telling the
// dispatcher to marshall the action onto the UI thread to execute it!
dispatcher.BeginInvoke(action, dispatcherPriority);
您正在UI线程上执行长期运行的工作:/

不过,解决办法很简单。简单地把你的作品拉出来,并把它放在背景线程中。这是相同的代码,但工作正常(除非代码中出现其他问题)


在方法
Work
中,您正在后台线程上执行。每次调用
dispatcher.BeginInvoke
时,传递给此方法的操作将在UI线程上执行。看到你现在在做什么了吗?请再次查看此代码

// Here, we are on a background thread
action = () =>
{
    // This action is NOT executing yet!  We are just defining it.
    UpdateProgress(10, "Sampling calculations");
    // This is going to execute on the thread that executes this action!
    viewModel1 = Application.GetEchantillonnage();//Long process
};
// here, we are still on the background thread, but we are telling the
// dispatcher to marshall the action onto the UI thread to execute it!
dispatcher.BeginInvoke(action, dispatcherPriority);
您正在UI线程上执行长期运行的工作:/

不过,解决办法很简单。简单地把你的作品拉出来,并把它放在背景线程中。这是相同的代码,但工作正常(除非代码中出现其他问题)


您的代码不断进入后台线程,以便在UI线程上执行长时间运行的任务。Dispatcher.BeginInvoke将代理封送回UI线程

试试这个:

   private void RunOnUI(Action uiAction, DispatcherPriority dispatcherPriority = DispatcherPriority.Background)
   {
        dispatcher.BeginInvoke(uiAction, dispatcherPriority);
   }

   public void Work(object sender, DoWorkEventArgs e)
   {
        var dispatcher = e.Argument as Dispatcher;
        var dispatcherPriority = DispatcherPriority.Background;
        Action action;

    runOnUI(() =>
    {
        UpdateStatut(StatutsInformation.Pending);
    });

    ViewModel1 viewModel1 = null;
    RunOnUI(() =>
    {
        UpdateProgress(10, "Sampling calculations");
    });
    viewModel1 = Application.GetEchantillonnage();//Long process

    List<double> lengthList = null;
    RunOnUI(() =>
    {
        UpdateProgress(20, "Length calculations");            
    });
    lengthList = AlgorithmLibrary.LengthCalculations(viewModel1);//Long process        

    ViewModel2 viewModel2 = null;
    RunOnUI(() =>
    {
        UpdateProgress(30, "Engine calculations");
    };
        viewModel2 = Application.GetEngine();//Long process
        AlgorithmLibrary.EngineCalculations(viewModel2);//Long process
        var FilteredLength = AlgorithmLibrary.LengthFilter(lengthList);//Long process

    ///... Others actions executed incrementing the progress value to 100%

    RunOnUI(() =>
    {
        UpdateStatut(StatutsInformation.Finished);
    });
}
private void rununui(Action uiAction,DispatcherPriority DispatcherPriority=DispatcherPriority.Background)
{
dispatcher.BeginInvoke(uiAction,dispatcherPriority);
}
公共作废工作(对象发送者、DoWorkEventArgs e)
{
var dispatcher=e.作为调度程序的参数;
var dispatcherPriority=dispatcherPriority.Background;
行动;
runOnUI(()=>
{
更新(状态信息待定);
});
ViewModel1 ViewModel1=null;
RunOnUI(()=>
{
UpdateProgress(10,“抽样计算”);
});
viewModel1=Application.GetEchantillonnage();//长进程
列表长度列表=null;
RunOnUI(()=>
{
UpdateProgress(20,“长度计算”);
});
lengthList=AlgorithmLibrary.LengthCalculations(viewModel1);//长进程
ViewModel2 ViewModel2=null;
RunOnUI(()=>
{
UpdateProgress(30,“发动机计算”);
};
viewModel2=Application.GetEngine();//长进程
AlgorithmLibrary.EngineCalculations(viewModel2);//长过程
var FilteredLength=AlgorithmLibrary.LengthFilter(lengthList);//长进程
///…执行的其他操作将进度值增加到100%
RunOnUI(()=>
{
UpdateStatut(StatutsInformation.Finished);
});
}

您的代码不断闯入后台线程,在UI线程上执行长时间运行的任务。Dispatcher.BeginInvoke将代理封送回UI线程

试试这个:

   private void RunOnUI(Action uiAction, DispatcherPriority dispatcherPriority = DispatcherPriority.Background)
   {
        dispatcher.BeginInvoke(uiAction, dispatcherPriority);
   }

   public void Work(object sender, DoWorkEventArgs e)
   {
        var dispatcher = e.Argument as Dispatcher;
        var dispatcherPriority = DispatcherPriority.Background;
        Action action;

    runOnUI(() =>
    {
        UpdateStatut(StatutsInformation.Pending);
    });

    ViewModel1 viewModel1 = null;
    RunOnUI(() =>
    {
        UpdateProgress(10, "Sampling calculations");
    });
    viewModel1 = Application.GetEchantillonnage();//Long process

    List<double> lengthList = null;
    RunOnUI(() =>
    {
        UpdateProgress(20, "Length calculations");            
    });
    lengthList = AlgorithmLibrary.LengthCalculations(viewModel1);//Long process        

    ViewModel2 viewModel2 = null;
    RunOnUI(() =>
    {
        UpdateProgress(30, "Engine calculations");
    };
        viewModel2 = Application.GetEngine();//Long process
        AlgorithmLibrary.EngineCalculations(viewModel2);//Long process
        var FilteredLength = AlgorithmLibrary.LengthFilter(lengthList);//Long process

    ///... Others actions executed incrementing the progress value to 100%

    RunOnUI(() =>
    {
        UpdateStatut(StatutsInformation.Finished);
    });
}
private void rununui(Action uiAction,DispatcherPriority DispatcherPriority=DispatcherPriority.Background)
{
dispatcher.BeginInvoke(uiAction,dispatcherPriority);
}
公共作废工作(对象发送者、DoWorkEventArgs e)
{
var dispatcher=e.作为调度程序的参数;
var dispatcherPriority=dispatcherPriority