取消異步方法我有一個使用一個外部庫連接到串行設備,併發送一些命令無頭UWP應用。它運行一個無限循環(while true),循環之間暫停10分鐘。測量過程大約需要4分鐘。 外部庫需要運行3次測量,並在每次測量後通過引發事件發出信號。第四次當事件發生時,我知道我可以返回結果。調用事件
4小時後(+/-幾秒鐘)庫將停止籌款活動(通常是引發事件的一個或2次,然後停止,沒有錯誤,沒有什麼)。
我在DoMeasureAsync()下面的CancellationTokenSource中實現,本應在8分鐘後在TaskCompletionSource上設置IsCancelled屬性,以便任務返回並繼續循環。
問題: 當測量沒有完成(在NMeasureCompletionSource從來沒有得到它的結果在課堂CMeasure設置),從nMeasureCompletionSource任務永遠不會取消。在RespondToCancellationAsync()中定義的委託應該在8分鐘後運行。
如果測量運行正常,我可以在在
taskAtHand.ContinueWith((x) =>
{
Logger.LogDebug("Disposing CancellationTokenSource...");
cancellationTokenSource.Dispose();
});
代碼被調用的日誌中看到。
編輯: 是否有可能在GC 4小時後進來,可能會釋放一些變量和這樣做使得應用無法將命令發送到傳感器? - 這是不是這樣的
缺少什麼我在這裏?
//this gets called in a while (true) loop
public Task<PMeasurement> DoMeasureAsync()
{
nMeasureCompletionSource = new TaskCompletionSource<PMeasurement>();
cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(8));
var t = cMeasure.Run(nitrateMeasureCompletionSource, cancellationTokenSource.Token);
var taskAtHand = nitrateMeasureCompletionSource.Task;
taskAtHand.ContinueWith((x) =>
{
Logger.LogDebug("Disposing CancellationTokenSource...");
cancellationTokenSource.Dispose();
});
return taskAtHand;
}
public class CMeasure
{
public async Task Run(TaskCompletionSource<PMeasurement> tcs, CancellationToken cancellationToken)
{
try
{
NMeasureCompletionSource = tcs;
CancellationToken = cancellationToken;
CancellationToken.Register(async() => await RespondToCancellationAsync(), useSynchronizationContext: false);
CloseDevice(); //Closing device if for some reason is still open
await Task.Delay(2500);
TheDevice = await GetDevice();
measurementsdone = 0;
Process(); //start the first measurement
}
catch (Exception ex)
{
DisconnectCommManagerAndCloseDevice();
NMeasureCompletionSource.SetException(ex);
}
}
public async Task RespondToCancellationAsync()
{
if (!NitrateMeasureCompletionSource.Task.IsCompleted)
{
Logger.LogDebug("Measure Completion Source is not completed. Cancelling...");
NMeasureCompletionSource.SetCanceled();
}
DisconnectCommManagerAndCloseDevice();
await Task.Delay(2500);
}
private void Process()
{
if (measurementsdone < 3)
{
var message = Comm.Measure(m); //start a new measurement on the device
}
else
{
...
NMeasureCompletionSource.SetResult(result);
}
}
//the method called when the event is raised by the external library
private void Comm_EndMeasurement(object sender, EventArgs e)
{
measurementsdone++;
Process();
}
}
「的GC 4小時後進來,可能會釋放一些變量和這樣做使得應用無法將命令發送到傳感器,可以嗎?」 - 你如何得出這個假設?強烈引用的對象不會被GC收集。即使他們願意,那麼你應該得到一些空指針異常或類似的東西。 – Fildor
@Fildor在這一刻我可以想到任何東西:) –
哦,*那*絕望......在這種情況下,我會隔離第三方並在測試項目中測試它的行爲。這個項目不會做任何事情,而是開始處理「在設備上」,看看它是否提高了回調。也許可以測量往返時間。如果這顯示相同的行爲,我會聯繫製造商並尋求幫助。如果它運行正常並且穩定,那麼我會創建一些模擬來代替第三方,這樣您可以更好地調試整體設計。哦,並用伐木膏抹它。您稍後可以再次刪除它,但如果您不知道發生了什麼,請讓代碼告訴您。 – Fildor