C# 任务阻塞UI线程

C# 任务阻塞UI线程,c#,wpf,multithreading,mvvm,C#,Wpf,Multithreading,Mvvm,我在wpf解决方案中有一个Primedcommand类,用于执行快速操作,然后在另一个线程上执行任务,以防止ui线程被阻塞: public void Execute(object parameter) { if (CanExecute(parameter)) { System.Windows.Application.Current.Dispatcher.Invoke(() => { _primer(); }); Task.Factory.S

我在wpf解决方案中有一个Primedcommand类,用于执行快速操作,然后在另一个线程上执行任务,以防止ui线程被阻塞:

public void Execute(object parameter)
{
    if (CanExecute(parameter))
    {
        System.Windows.Application.Current.Dispatcher.Invoke(() => { _primer(); });

        Task.Factory.StartNew(() => { _execute(parameter); }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
    }
}
和PrimedCommand构造函数:

public PrimedCommand(Action primer, Action<object> execute, Predicate<object> canExecute)
{
    if (primer == null)
        throw new ArgumentNullException("primer");

    if (execute == null)
        throw new ArgumentNullException("execute");

    _primer = primer;

    _execute = execute;
    _canExecute = canExecute;
}
从我们称之为“执行”按钮开始,primer的任务是设置一个属性的值,该属性向用户显示操作处于活动状态

这很好,但是,当我单击cancel按钮时,它会将status属性更新为Canceling,然后在worker类中设置一个字段以指示操作正在取消,UI大约需要2秒钟来响应按钮单击。我尝试过Task.Run和Task.Factory.StartNew,使用各种重载,创建自己的工作线程似乎效果最好,但仍然不是我想要的方式

我要查找的是,您单击“执行”按钮,状态更新为活动(更新ui),绑定到该属性,然后单击“取消”按钮时,状态更改为“取消”,通知工作人员的任务设置相应字段(工作线程经常检查此字段,并在需要时退出)

不起作用的是工作线程阻止ui线程更新,以向用户显示操作正在取消。(状态设置为活动后,暂时无法单击取消按钮)

另外值得注意的是,该解决方案使用mvvm,其中状态是ui通过转换器绑定到的枚举值


任何问题请告诉我。

使用Dispatcher.Invoke从另一个线程更新UI。有很多这样的例子。比如:@David谢谢,但我已经在属性设置程序中这样做了。我确实尝试从调度程序线程调用该操作,但没有效果。请参阅更新的代码。“工作线程阻止UI线程更新”-您需要显示更多代码。在某个地方,您的代码正在阻止UI线程(可能是无意中等待工作线程!)。@DanPuzey您希望从工作类或命令调用的viewmodel委托中获得代码吗?使用Dispatcher.Invoke从另一个线程更新UI。有很多这样的例子。比如:@David谢谢,但我已经在属性设置程序中这样做了。我确实尝试从调度程序线程调用该操作,但没有效果。请参阅更新的代码。“工作线程阻止UI线程更新”-您需要显示更多代码。在某些地方,您的代码正在阻止UI线程(可能是无意中等待工作线程!)@DanPuzey您希望从工作类还是从命令调用的viewmodel委托中获得代码?
private static void AddChoices(ref Settings RunningSettings)
{
    if (Processes.ShouldExit) return;

    try
    {
        if (RunningSettings.Initialized)
        {
            if (Processes.ShouldExit) return;

            if (RunningSettings.WorkingDirectory != null)
            {
                DirectoryInfo workingDir = new DirectoryInfo(RunningSettings.WorkingDirectory);

                if (!workingDir.Exists)
                {
                    throw new DirectoryNotFoundException("The Source Directory Didn't Exist");
                }

                RunningSettings.CurrentStatus.AddMoment(new Moment("Loading Customers"));

                Dictionary<string, string> customerNames = new Dictionary<string, string>();
                Dictionary<string, string> jobNumbers = new Dictionary<string, string>();

                List<DirectoryInfo> availableFolders = new List<DirectoryInfo>();

                if (Tools.IsCustomer(workingDir))
                {
                    availableFolders.Add(workingDir);
                }
                else if (Tools.IsCustomerContainer(workingDir))
                {
                    availableFolders.AddRange(workingDir.EnumerateDirectories().Where(c => Tools.IsCustomer(c)));
                }
                else if (Tools.IsJob(workingDir))
                {
                    availableFolders.Add(workingDir.Parent);
                }

                foreach (DirectoryInfo customer in availableFolders)
                {
                    if (Processes.ShouldExit) return;

                    try
                    {
                        RunningSettings.CurrentStatus.AddMoment(new Moment(String.Format("  Loading Jobs For: {0}", customer)));

                        if (!customerNames.ContainsKey(customer.Name))
                        {
                            customerNames.Add(customer.Name, null); 
                        }

                        foreach (DirectoryInfo job in customer.GetDirectories().Where(j => Tools.IsJob(j)))
                        {
                            if (Processes.ShouldExit) return;

                            try
                            {
                                string tempNumber = job.Name.Substring(0, 6);

                                if (!jobNumbers.ContainsKey(tempNumber))
                                {
                                    jobNumbers.Add(tempNumber, customer.Name); 
                                }
                            }
                            catch (Exception except)
                            {
                                ErrorHandling.Handle(except, ref RunningSettings);
                            }
                        }
                    }
                    catch (Exception excep)
                    {
                        ErrorHandling.Handle(excep, ref RunningSettings);
                    }
                }

                int count = 0;
                int index = 0;

                if (customerNames != null && customerNames.Count > 0)
                {
                    RunningSettings.ClearCustomerCollection();

                    count = customerNames.Count;
                    foreach (KeyValuePair<string, string> customer in customerNames)
                    {
                        if (Processes.ShouldExit) break;

                        try
                        {
                            index++;
                            RunningSettings.AddCustomer(customer.Key, customer.Value, (index == count));
                        }
                        catch (Exception excep)
                        {
                            ErrorHandling.Handle(excep, ref RunningSettings);
                        }
                    }

                    RunningSettings.SortCustomers();
                }

                if (Processes.ShouldExit) return;

                count = 0;
                index = 0;

                if (jobNumbers != null && jobNumbers.Keys.Count > 0)
                {
                    RunningSettings.ClearJobCollection();

                    count = jobNumbers.Count;
                    foreach (KeyValuePair<string, string> job in jobNumbers)
                    {
                        if (Processes.ShouldExit) break;

                        try
                        {
                            index++;
                            RunningSettings.AddJob(job.Key, job.Value, (index == count));
                        }
                        catch (Exception excep)
                        {
                            ErrorHandling.Handle(excep, ref RunningSettings);
                        }
                    }

                    RunningSettings.SortJobs();
                }

                if (Processes.ShouldExit) return;

                RunningSettings.CurrentStatus.AddMoment(new Moment("Loading Customers Complete"));
            }
            else
            {
                throw new InvalidOperationException("The Working Directory Was Null");
            }
        }
        else
        {
            throw new InvalidOperationException("The Settings Must Be Initialized Before Customer Folders Can Be Enumerated");
        }
    }
    catch (Exception ex)
    {
        ErrorHandling.Handle(ex, ref RunningSettings);
    }
}
public static void Cancel()
{
    KeepRunning = false; // Bool watched by worker processes
}