当用户点击表单的某个部分时,我需要开始更新同一表单的另一个区域。这是使用单独的任务完成的。事实是,如果触发更新并且正在进行更新,我需要取消它,等待它完成,然后启动一个新的。
我是TPL的新手,由于时间限制,我不能使用.NET 5(我们有VS2012许可证,但尚未迁移我们的解决方案)。这是代码:
private mLoadGridLock = new Object();
private CancellationTokenSource mCancellationTokenSource;
private bool mLoadingFrames;
private Task mLoadingTask;
private List<string> mFramesList;
public FrameLoader(){
InitializeComponent();
mLoadingFrames = false;
mCancellationTokenSource = new CancellationTokenSource();
}
public void LoadGrid(){
lock (mLoadGridLock) {
if (mStudiesGrid.RowCount <= 0)
return;
Debug.WriteLine("--->LoadGrid Called");
if (mLoadingFrames) {
mCancellationTokenSource.Cancel();
Debug.WriteLine("--->Waiting for cancellation...");
mLoadingTask.Wait();
Debug.WriteLine("--->Wait for cancellation over!");
}
Debug.WriteLine("--->Launching new task");
mLoadingTask = Task.Factory.StartNew(() => LoadFrames(), mCancellationTokenSource.Token);
}
}
private void LoadFrames(){
mLoadingFrames = true;
Debug.WriteLine(" +++> Loader task started!");
int i = 0;
BeginInvoke(() => flp.Controls.Clear());
mFramesList = FrameRules.GenerateFrameList(this);
if (mFramesList <= 0)
return;
foreach (string framePath in mFramesList) {
if (mCancellationTokenSource.Token.IsCancellationRequested) {
mLoadingFrames = false;
Debug.WriteLine(" +++>Loader task cancelled");
return;
}
Debug.WriteLine(" +++>Loading frame " + i.ToString());
i = i + 1;
FrameOfReference fofr = new FrameOfReference();
fofr.BackgroundImage = My.Resources.Loading;
BeginInvoke(() => flp.Controls.Add(fofr));
Thread.Sleep(3000);
BeginInvoke(() => fofr.BackgroundImage == My.Resources.Done);
}
mLoadingFrames = false;
Debug.WriteLine(" +++>Loader task finished");
}
第一次运行正常,但在第二次运行时我遇到了僵局。这是调试输出,它是一致的(它总是相同的):
--->LoadGrid Called
--->Launching new task
+++> Loader task started!
+++>Loading frame 0
+++>Loading frame 1
The thread 'ShowMessage-Execute' (0x168c) has exited with code 0 (0x0).
The thread 'Win32 Thread' (0x168c) has exited with code 0 (0x0).
+++>Loader task finished
--->LoadGrid Called
--->Launching new task
+++> Loader task started!
+++>Loading frame 0
--->LoadGrid Called
--->Waiting for cancellation...
很明显,问题是由于第二次触发更新时LoadGrid被调用两次引起的;这就是我添加lock
块的原因。但这仍然悬而未决......这是我第一次使用TPL,所以任何输入都是受欢迎的。
更新:将lock(this)
更改为lock(mLoadGridLock)
后,死锁消失,但在第二次或第三次尝试时,它不会加载任何帧,从那时起它没有加载。这是一个日志:
--->LoadGrid Called
--->Launching new task
+++> Loader task started!
+++>Loading frame 0
The thread 'ShowMessage-Execute' (0xe50) has exited with code 0 (0x0).
The thread 'Win32 Thread' (0xe50) has exited with code 0 (0x0).
+++>Loading frame 1
+++>Loader task finished
--->LoadGrid Called
--->Launching new task
+++> Loader task started!
+++>Loading frame 0
--->LoadGrid Called
--->Waiting for cancellation...
+++>Loader task cancelled
--->Wait for cancellation over!
--->Launching new task