ここに私のシナリオがあります:ユーザーが地図上のポイントの集まりを無期限にするWPFボタンをクリックします。ユーザーが「収集完了」ボタンをクリックすると、CollectPoints()
タスクを完了します。ここでCancellationTokenを使用してネストされたタスクを中断する
は私SegmentRecorder
クラスの一部です:私はラインwhile (!token.IsCancellationRequested)
にブレークポイントを入れて、キャンセルボタンをクリックすると
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();
}
:ここ
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();
}
は、私の見解モデルの関連部分です、私はその点に決して到達しません。
キャンセルトークンを正しい方法で使用していますか?それはwhile
条件!token.IsCancellationRequested
あなたがCancellationTokenSource
のCancel()
メソッドを呼び出した後、初めてに当たるたび
サイドノート:あなたは、イベントハンドラではありません方法のために '非同期void'を使用しないでください。 – dymanoid
あなたは 'CollectPoint'の中で取り消しを処理する必要があります、それはおそらく今どこに待っているのでしょうか。 – JSteward
ユーザーがポイントの収集を停止すると、少なくとも 'CollectPoint'タスクが完了するために少なくとももう1つは収集する必要があり、これはあなたの' while'の実行を一時停止しています。 'CollectPoint'の外側で' tcs'をホールドして、それを完了させるか、またはユーザーが収集を停止したいときにキャンセルします。すると、あなたの期待どおりに終了します。 – JSteward