C# 任务阻塞UI线程
我在wpf解决方案中有一个Primedcommand类,用于执行快速操作,然后在另一个线程上执行任务,以防止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
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
}