【发布时间】:2017-09-15 22:45:16
【问题描述】:
这是我的场景:用户单击一个 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) 行上设置断点并单击取消按钮时,我永远不会到达那个点。
我在这里以正确的方式使用取消令牌吗?
【问题讨论】:
-
附注:您不应该将
async void用于不是事件处理程序的方法。 -
您还需要在
CollectPoint中处理取消,这可能就是它现在正在等待的地方。 -
一旦用户停止收集积分,他们需要至少再收集一个才能完成
CollectPoint任务,这将暂停执行您的while。在CollectPoint外面按住tcs并在用户想要停止收集时完成或取消它,然后您的while 将按预期完成。
标签: c# wpf async-await