C#同步方法调用终止当前处理
我有一个绑定到WPF视图的C#同步方法调用终止当前处理,c#,wpf,multithreading,C#,Wpf,Multithreading,我有一个绑定到WPF视图的ObservableCollection。有一种方法可以刷新集合的内容。此方法正在后台线程中处理,需要几秒钟的时间。为了避免错误,调用的方法是同步的 即使之前的处理尚未完成,也可能会调用该方法。在这种情况下,我希望停止当前处理并启动新的处理 private ObservableCollection<string> col = new ObservableCollection<string>(); private async void Refre
ObservableCollection
。有一种方法可以刷新集合的内容。此方法正在后台线程中处理,需要几秒钟的时间。为了避免错误,调用的方法是同步的
即使之前的处理尚未完成,也可能会调用该方法。在这种情况下,我希望停止当前处理并启动新的处理
private ObservableCollection<string> col = new ObservableCollection<string>();
private async void Refresh()
{
var ui = TaskScheduler.FromCurrentSynchronizationContext();
await Task.Factory.StartNew(() =>
{
return GetNewObjects();
}).ContinueWith(t =>
{
col = t.Result;
}, ui);
}
[MethodImpl(MethodImplOptions.Synchronized)]
private ObservableCollection<string> GetNewObjects()
{
// processing
}
private observetecollection col=new observetecollection();
私有异步无效刷新()
{
var ui=TaskScheduler.FromCurrentSynchronizationContext();
等待任务。工厂。开始新建(()=>
{
返回GetNewObjects();
}).ContinueWith(t=>
{
col=t.结果;
},用户界面);
}
[MethodImpl(MethodImplOptions.Synchronized)]
私有ObservableCollection GetNewObjects()
{
//加工
}
我的想法是在Refresh()中保存相应的
任务的引用
,如果已经有正在运行的任务,则签入每个调用。这是停止任务的正确(安全)方法吗?您应该始终遵循async
/wait
路径
要取消任务,请使用CancellationTokenSource
及其CancellationToken
private ObservableCollection<string> col = new ObservableCollection<string>();
private CancellationTokenSource _refreshCancellation;
private async void Refresh()
{
// cancel the last Refresh action
if ( _refreshCancellation != null )
{
_refreshCancellation.Cancel();
}
_refreshCancellation = new CancellationTokenSource();
var token = _refreshCancellation.Token;
try
{
var newObjects = await GetNewObjectsAsync( token );
col = new ObservableCollection<string>( newObjects );
}
catch ( OperationCanceledException )
{
}
}
private async Task<ICollection<string>> GetNewObjectsAsync( CancellationToken cancellationToken )
{
for ( int i = 0; i < 5; i++ )
{
await Task.Delay( 100 ).ConfigureAwait( false );
// check if we had to cancel, but only where it is safe to cancel
cancellationToken.ThrowIfCancellationRequested();
}
return new List<string> { "a", "b", "c", };
}
private observetecollection col=new observetecollection();
私有取消令牌源\u刷新取消;
私有异步无效刷新()
{
//取消上次刷新操作
如果(_refreshCancellation!=null)
{
_refreshCancellation.Cancel();
}
_refreshCancellation=新的CancellationTokenSource();
var token=\u refreshCancellation.token;
尝试
{
var newObjects=await GetNewObjectsAsync(令牌);
col=新的可观测集合(新对象);
}
捕获(操作取消异常)
{
}
}
专用异步任务GetNewObjectsAsync(CancellationToken CancellationToken)
{
对于(int i=0;i<5;i++)
{
等待任务。延迟(100)。配置等待(false);
//检查我们是否必须取消,但只在安全的情况下取消
cancellationToken.ThrowIfCancellationRequested();
}
返回新列表{“a”、“b”、“c”、};
}
您可能会尝试使用取消令牌。顺便问一下,为什么不Task.Run()
?您是否坚持使用.NET 4.0?老实说,没有。。我对.net一无所知。我正在寻找一种很好的方法来刷新视图,而不冻结ui线程。这是我的第一个工作方式。为什么要使用Task.Run()?有什么好处?我认为这是不可能的。UI线程上的延续是一个致命的细节,并且总是会导致死锁。并非唯一的问题,GetNewObjects()必须使用UI中的某种数据来生成不同的结果。我们看不到,但唯一有意义的是。您不能允许该数据在执行时更改。每次单击另一个ObservableCollection中的复选框时,都将调用GetNewObjects()。每个选中的复选框都将是GetNewObjects()方法的输入。实际上,“[MethodImpl(MethodImplOptions.Synchronized)]会导致顺序处理。但这就是问题所在。当方法被调用2次时,有趣的结果是最后一次调用。每次调用后,前面的结果不再相关。Task.Run()
是在.NET 4.5+中启动任务的首选方法,请阅读以了解详细信息。感谢您的建议。我的后台任务是SQL查询,而不是循环。所以我需要终止这个SQL操作。是否可以通过CancellationToken实现这一点?在阅读了这里的帖子和这些令牌的功能之后,我发现了这个新问题。如果你有新问题,那么如果你找不到任何解决方案,你应该问一个新问题。这就是SO的工作原理这里有一个关于如何处理取消SQL查询的问题,谢谢你的帮助。。你说得对。我遇到了一个新问题。我会尽力解决这个问题。否则我会问一个新问题。然而,你的回答解决了这个问题。