[英]Use a CancellationToken to interrupt nested tasks
這是我的場景:用戶單擊WPF按鈕,該按鈕啟動地圖上點集合的開放時段。 當用戶單擊“完成收集”按鈕時,我希望CollectPoints()
任務完成。
以下是我的SegmentRecorder
類:
private CancellationTokenSource _cancellationToken;
public virtual async void RecordSegment(IRoadSegment segment)
{
_cancellationToken = new CancellationTokenSource();
var token = _cancellationToken.Token;
// await user clicking points on map
await CollectPoints(token);
// update the current segment with the collected shape.
CurrentSegment.Shape = CurrentGeometry as Polyline;
}
// collect an arbitrary number of points and build a polyline.
private async Task CollectPoints(CancellationToken token)
{
var points = new List<MapPoint>();
while (!token.IsCancellationRequested)
{
// wait for a new point.
var point = await CollectPoint();
points.Add(point);
// add point to current polyline
var polylineBuilder = new PolylineBuilder(points, SpatialReferences.Wgs84);
CurrentGeometry = polylineBuilder.ToGeometry();
// draw points
MapService.DrawPoints(CurrentGeometry);
}
}
// collect a point from map click.
protected override Task<MapPoint> CollectPoint()
{
var tcs = new TaskCompletionSource<MapPoint>();
EventHandler<IMapClickedEventArgs> handler = null;
handler = (s, e) =>
{
var mapPoint = e.Geometry as MapPoint;
if (mapPoint != null)
{
tcs.SetResult(new MapPoint(mapPoint.X, mapPoint.Y, SpatialReferences.Wgs84));
}
MapService.OnMapClicked -= handler;
};
MapService.OnMapClicked += handler;
return tcs.Task;
}
public void StopSegment(){
// interrupt the CollectPoints task.
_cancellationToken.Cancel();
}
以下是我的視圖模型的相關部分:
public SegmentRecorder SegmentRecorder { get; }
public RelayCommand StopSegment { get; }
public ViewModel(){
StopSegment = new RelayCommand(ExecuteStopSegment);
SegmentRecorder = new SegmentRecorder();
}
// execute on cancel button click.
public void ExecuteStopSegment(){
SegmentRecorder.StopSegment();
}
當我while (!token.IsCancellationRequested)
上放置一個斷點並單擊取消按鈕時,我從未達到過這一點。
我是否以正確的方式使用取消令牌?
只要遇到while
條件, CollectPoints
方法就會返回!token.IsCancellationRequested
在您調用CancellationTokenSource
的Cancel()
方法后第一次返回。
而里面的代碼的任務不會被取消while
循環仍在執行。
正如@JSteward在他的評論中建議的那樣,你應該在你的StopSegment()
方法中取消或完成TaskCompletionSource
。
像這樣的東西:
public virtual async void RecordSegment(IRoadSegment segment)
{
_cancellationToken = new CancellationTokenSource();
var token = _cancellationToken.Token;
// await user clicking points on map
await CollectPoints(token);
// update the current segment with the collected shape.
CurrentSegment.Shape = CurrentGeometry as Polyline;
}
// collect an arbitrary number of points and build a polyline.
private async Task CollectPoints(CancellationToken token)
{
var points = new List<MapPoint>();
while (!token.IsCancellationRequested)
{
try
{
// wait for a new point.
var point = await CollectPoint(token);
//...
}
catch (Exception) { }
}
}
private TaskCompletionSource<MapPoint> tcs;
protected override Task<MapPoint> CollectPoint()
{
tcs = new TaskCompletionSource<MapPoint>();
//...
return tcs.Task;
}
public void StopSegment()
{
// interrupt the CollectPoints task.
_cancellationToken.Cancel();
tcs.SetCanceled();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.