【发布时间】:2017-01-05 11:31:19
【问题描述】:
背景:我正在开发一个应用程序,它本质上是一个用于远程服务器的缓存文件浏览器。当用户单击一个目录时,它将从目录树的本地副本中向他们显示其子目录。然后它还会启动一个“即发即弃”任务,以从服务器检索对视图中目录的更改,并更新缓存和用户正在显示的内容。
private CancellationTokenSource _cts;
private SemaphoreSlim _myTaskBlocker = new SemaphoreSlim(1,1);
public void CancelMyTask()
{
_cts?.Cancel();
}
public async Task FireAndForgetWithCancel()
{
await _myTaskBlocker.WaitAsync();
_cts = new CancellationTokenSource();
try
{
//Some potentially long running code.
token.ThrowIfCancellationRequested();
}
catch(OperationCancelledException){}
finally
{
_cts.dispose();
_cts = null;
_myTaskBlocker.Release();
}
}
编辑 1:可以这样做吗? SemaphoreSlim 有点像 _cts 上的锁定,所以我不需要在进行更改之前锁定它吗?
编辑 2:所以我得出的结论是,这是一个坏主意,并且无法以我最初希望的方式真正实现。
我的解决方案是让 ViewModel 发送请求并监听更新事件。
public class Model
{
// Thread safe observable collection with AddRange.
public ObservableCollectionEx<file> Files { get; }
// A request queue.
public ActionBlock<request> Requests { get; }
}
public class ViewModel
{
public ObservableCollectionEx<file> FilesTheUserSees { get; }
public ViewModel()
{
Model.Files.CollectionChanged += FileCollectionChanged;
}
public async Task UserInstigatedEvent()
{
// Do some stuff to FilesTheUserSees here.
// Request the model to check for updates. Blocks only as long as it takes to send the message.
await Model.Requests.SendAsync(new request());
}
public void FileCollectionChanged(object sender, CollectionChangedEventArgs e)
{
// Check to see if there are any new files in Files.
// If there are new files that match the current requirements add them to FilesTheUserSees.
}
}
需要注意的一些问题是,现在依赖 ObservableCollectionsEx 来实现线程安全,但这是一个可以实现的目标,并且即使它有一些缺点也更容易调试。
【问题讨论】:
-
您要求进行代码审查?
-
也许吧?我是 C# 的新手,还不太了解该做什么和不该做什么。我想我是在问这是否是糟糕的设计。
-
你可以使用hangfire来运行后台作业和fireandforgot hangfire.io
标签: c# async-await cancellationtokensource