首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >任务取消不停止任务执行

任务取消不停止任务执行
EN

Stack Overflow用户
提问于 2016-07-06 15:17:56
回答 1查看 1.7K关注 0票数 4

我有一个Task,它查询一个活动目录,并将结果填充到列表中。我已经设置了我的任务,以便可以取消它,但是,当调用cancel时,任务继续执行它的工作。我知道任务已被取消,因为它返回,并且在任务返回时要执行的操作被运行,但是查询仍然在后台运行,使用内存和处理能力。任务可以重复启动和“取消”,任务的每一次迭代都在运行并使用资源。我怎样才能使取消实际上取消呢?

ViewModel

代码语言:javascript
复制
private async Task RunQuery(QueryType queryType,
    string selectedItemDistinguishedName = null)
{
    StartTask();
    try
    {
        _activeDirectoryQuery = new ActiveDirectoryQuery(queryType,
            CurrentScope, selectedItemDistinguishedName);
        await _activeDirectoryQuery.Execute();
        Data = _activeDirectoryQuery.Data.ToDataTable().AsDataView();
        CurrentQueryType = queryType;
    }
    catch (ArgumentNullException)
    {
        ShowMessage(
            "No results of desired type found in selected context.");
    }
    catch (OutOfMemoryException)
    {
        ShowMessage("The selected query is too large to run.");
    }
    FinishTask();
}

private void CancelCommandExecute()
{
    _activeDirectoryQuery?.Cancel();
}

ActiveDirectoryQuery

代码语言:javascript
复制
public async Task Execute()
{
    _cancellationTokenSource = new CancellationTokenSource();
    var taskCompletionSource = new TaskCompletionSource<object>();
    _cancellationTokenSource.Token.Register(
        () => taskCompletionSource.TrySetCanceled());
    DataPreparer dataPreparer = null;
    var task = Task.Run(() =>
    {
        if (QueryTypeIsOu())
        {
            dataPreparer = SetUpOuDataPreparer();
        }
        else if (QueryTypeIsContextComputer())
        {
            dataPreparer = SetUpComputerDataPreparer();
        }
        else if (QueryTypeIsContextDirectReportOrUser())
        {
            dataPreparer = SetUpDirectReportOrUserDataPreparer();
        }
        else if (QueryTypeIsContextGroup())
        {
            dataPreparer = SetUpGroupDataPreparer();
        }
        Data = GetData(dataPreparer);
    },
    _cancellationTokenSource.Token);
    await Task.WhenAny(task, taskCompletionSource.Task);
}

public void Cancel()
{
    _cancellationTokenSource?.Cancel();
}

Cancel()由绑定到ButtonCommand调用。这个任务可能需要几分钟才能执行,并且可以消耗几百兆字节的内存。如果有帮助,我可以提供任何引用的方法或任何其他信息。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-07-06 16:38:48

取消是合作的,如果要取消操作,则需要编辑函数以取消操作。所以执行会变成

代码语言:javascript
复制
public async Task Execute()
{
    _cancellationTokenSource = new CancellationTokenSource();
    var taskCompletionSource = new TaskCompletionSource<object>();

    //Token registrations need to be disposed when done.
    using(_cancellationTokenSource.Token.Register(
        () => taskCompletionSource.TrySetCanceled()))
    {
        DataPreparer dataPreparer = null;
        var task = Task.Run(() =>
        {
            if (QueryTypeIsOu())
            {
                dataPreparer = SetUpOuDataPreparer(_cancellationTokenSource.Token);
            }
            else if (QueryTypeIsContextComputer())
            {
                dataPreparer = SetUpComputerDataPreparer(_cancellationTokenSource.Token);
            }
            else if (QueryTypeIsContextDirectReportOrUser())
            {
                dataPreparer = SetUpDirectReportOrUserDataPreparer(_cancellationTokenSource.Token);
            }
            else if (QueryTypeIsContextGroup())
            {
                dataPreparer = SetUpGroupDataPreparer(_cancellationTokenSource.Token);
            }
            Data = GetData(dataPreparer, _cancellationTokenSource.Token);
        },
        _cancellationTokenSource.Token);
        await Task.WhenAny(task, taskCompletionSource.Task);
   }
}

然后从这些方法里面。如果在这些函数中有循环,则需要从循环内部调用token.ThrowIfCancellationRequested()。如果不循环并调用一些外部API,则需要使用该API的取消方法,希望API将接受CancellationToken,如果不接受,则需要调用.Cancel()方法使用Register方法,就像在Execute中所做的那样。

如果API不公开取消查询的方法,那么安全早期停止查询的唯一方法是将查询移动到单独的exe。当您执行查询时,您需要执行一个var proc = Process.Start(...)来启动exe。要与它通信,可以使用某种形式的IPC (如WCF在命名管道上 ),您可以在进程开始之前生成一个Guid,并将它作为参数传入,然后使用该guid作为命名管道的名称。如果需要尽早结束查询,则需要执行proc.Kill()来结束外部进程。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38227614

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档