이 Windows 8 WinRT 작업을 가지고 놀고 있는데, 아래 방법을 사용하여 작업을 취소하려고 하는데 어느 정도는 작동합니다. 취소 알림 메서드가 호출되어 작업이 취소되었다고 생각하지만 백그라운드에서 작업이 계속 실행되고 완료된 후에는 작업 상태가 항상 완료된 상태로 표시되고 취소되지 않습니다. 작업이 취소되었을 때 작업을 완전히 중지할 수 있는 방법이 있나요?
private async void TryTask()
{
CancellationTokenSource source = new CancellationTokenSource();
source.Token.Register(CancelNotification);
source.CancelAfter(TimeSpan.FromSeconds(1));
var task = Task<int>.Factory.StartNew(() => slowFunc(1, 2), source.Token);
await task;
if (task.IsCompleted)
{
MessageDialog md = new MessageDialog(task.Result.ToString());
await md.ShowAsync();
}
else
{
MessageDialog md = new MessageDialog("Uncompleted");
await md.ShowAsync();
}
}
private int slowFunc(int a, int b)
{
string someString = string.Empty;
for (int i = 0; i < 200000; i++)
{
someString += "a";
}
return a + b;
}
private void CancelNotification()
{
}
.NET 4.0에서 도입되었으며 그 이후로 거의 변경되지 않은 취소와 작업 기반 비동기 패턴을 읽어보시고, 동기
메서드와 함께 CancellationToken
을 사용하는 방법에 대한 지침을 확인하세요.
요약하자면, 취소를 지원하는 각 메서드에 CancellationToken
을 전달하고, 해당 메서드는 이를 주기적으로 확인해야 합니다.
private async Task TryTask()
{
CancellationTokenSource source = new CancellationTokenSource();
source.CancelAfter(TimeSpan.FromSeconds(1));
Task<int> task = Task.Run(() => slowFunc(1, 2, source.Token), source.Token);
// (A canceled task will raise an exception when awaited).
await task;
}
private int slowFunc(int a, int b, CancellationToken cancellationToken)
{
string someString = string.Empty;
for (int i = 0; i < 200000; i++)
{
someString += "a";
if (i % 1000 == 0)
cancellationToken.ThrowIfCancellationRequested();
}
return a + b;
}
또는 slowFunc
를 수정하지 않기 위해(예를 들어 소스 코드에 액세스할 수 없다고 가정할 때):
var source = new CancellationTokenSource(); //original code
source.Token.Register(CancelNotification); //original code
source.CancelAfter(TimeSpan.FromSeconds(1)); //original code
var completionSource = new TaskCompletionSource<object>(); //New code
source.Token.Register(() => completionSource.TrySetCanceled()); //New code
var task = Task<int>.Factory.StartNew(() => slowFunc(1, 2), source.Token); //original code
//original code: await task;
await Task.WhenAny(task, completionSource.Task); //New code
https://github.com/StephenCleary/AsyncEx 의 멋진 확장 메서드를 사용하여 다음과 같이 간단하게 만들 수도 있습니다:
await Task.WhenAny(task, source.Token.AsTask());
public async Task<Results> ProcessDataAsync(MyData data)
{
var client = await GetClientAsync();
await client.UploadDataAsync(data);
await client.CalculateAsync();
return await client.GetResultsAsync();
}
스케쳐내 취소 후 통과될 수 있도록 지원할 수 있는 가장 손쉬운 방법이 될 수 있으면 증표지 확인하고 취소되었는지 상호 간에 비동기 메서드 호출 (또는 사용 콘티누에비트). 매우 긴 경우 페이징됩니다 기다림커서 귈이예요 취소할 수 있지만 실행할 수 있습니다. 내가 만든 것이 아니라 어떤 방법을 조금 빨리 페일오버합니다 @@@취소됨.
public static class TaskExtensions
{
public static async Task<T> WaitOrCancel<T>(this Task<T> task, CancellationToken token)
{
token.ThrowIfCancellationRequested();
await Task.WhenAny(task, token.WhenCanceled());
token.ThrowIfCancellationRequested();
return await task;
}
public static Task WhenCanceled(this CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<bool>();
cancellationToken.Register(s => ((TaskCompletionSource<bool>)s).SetResult(true), tcs);
return tcs.Task;
}
}
그 후 사용할 수 있도록 추가하기만 드와이토르칸첼 (토큰) '' 어떤 비동기 호출:
public async Task<Results> ProcessDataAsync(MyData data, CancellationToken token)
{
Client client;
try
{
client = await GetClientAsync().WaitOrCancel(token);
await client.UploadDataAsync(data).WaitOrCancel(token);
await client.CalculateAsync().WaitOrCancel(token);
return await client.GetResultsAsync().WaitOrCancel(token);
}
catch (OperationCanceledException)
{
if (client != null)
await client.CancelAsync();
throw;
}
}
참고로 이 기다리고 또 계속 실행하시겠습니까 조교하실 작업을 멈추지 않을 것이라고 말했다. # 39, you& 다른 방법을 사용해야 하는 등 'll call 이 예에서 고만하세요 캔셀라인스' 또는 '을' 작업 '같은' 더 좋은 것은 전달하십시오 캔셀라티온트킨 처리할 수 있도록 취소되면서 결국. Isn& # 39, t 권장됨 스레드할 중단할 수 있다.
이미 승인 된 답변에 추가하고 싶습니다. 나는 이것에 갇혀 있었지만 완전한 이벤트를 처리하는 데 다른 길을 가고있었습니다. 대기를 실행하는 대신 완료된 핸들러를 작업에 추가합니다.
Comments.AsAsyncAction().Completed += new AsyncActionCompletedHandler(CommentLoadComplete);
이벤트 핸들러는 다음과 같습니다.
private void CommentLoadComplete(IAsyncAction sender, AsyncStatus status )
{
if (status == AsyncStatus.Canceled)
{
return;
}
CommentsItemsControl.ItemsSource = Comments.Result;
CommentScrollViewer.ScrollToVerticalOffset(0);
CommentScrollViewer.Visibility = Visibility.Visible;
CommentProgressRing.Visibility = Visibility.Collapsed;
}
이 경로를 사용하면 모든 처리가 이미 완료되어 작업이 취소되면 이벤트 핸들러가 트리거되고 거기서 취소 여부를 확인할 수 있습니다.