使用CancellationTokenSource仅运行一项任务

时间:2019-10-04 09:41:31

标签: task cancellationtokensource

第一手,我的应用程序在WPF中。 另一方面,我有一个任务方法来刷新只需要执行一次的某些视图。因此,如果该方法在第一个方法完成之前被第二次调用,它将取消第一个任务方法。

为实现这一目标,我找到了一个通常可以“正常工作”的解决方案,但是有时我会遇到一个例外:“ hwnd不能为IntPtr.Zero或null。”而且我不明白为什么我的第一个解决方案不起作用。

“有效”的解决方案:

private Tuple<Task, CancellationTokenSource> _manageErrorTask;
private void RefreshMyList()
{
    if (_manageErrorTask != null && !_manageErrorTask.Item1.IsCompleted)
    {
        _manageErrorTask.Item2.Cancel();
        _manageErrorTask.Item2.Dispose();
        _manageErrorTask.Item1.Dispose();
        _manageErrorTask = null;
    }

    var token = new CancellationTokenSource();
    CancellationToken ct = token.Token;
    ct.Register(() => Console.WriteLine("Cancel Token !! "));

    Task task = Task.Run(() =>
    {
        // Were we already canceled?
        if (ct.IsCancellationRequested) return;

        try
        {
            foreach (var userControl in MyList)
            {
                RT(() =>
                {
                    Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
                    {
                        var vm = userControl.DataContext as ViewModelBase;
                        vm?.Refresh("yololo");
                    }));

                },
                ct);

            }
        }
        catch(Exception e)
        {
            //Do nothing
        }

    }, ct);

    _manageErrorTask = Tuple.Create(task, token);
}

public static void RT(Action action, CancellationToken token)
{
    if (action == null)
        return;
    Task.Run(async () => {
        if (!token.IsCancellationRequested)
        {
            action();

        }
    }, token);
}

我的解决方案无效:

private Tuple<Task, CancellationTokenSource> _manageErrorTask;
private void RefreshMyList()
{
    if (_manageErrorTask != null && !_manageErrorTask.Item1.IsCompleted)
    {
        _manageErrorTask.Item2.Cancel();
        _manageErrorTask.Item2.Dispose();
        _manageErrorTask.Item1.Dispose();
        _manageErrorTask = null;
    }

    var token = new CancellationTokenSource();
    CancellationToken ct = token.Token;
    ct.Register(() => Console.WriteLine("Cancel Token !! "));

    Task task = Task.Run(() =>
    {
        // Were we already canceled?
        if (ct.IsCancellationRequested) return;

        try
        {
            foreach (var userControl in MyList)
            {
                Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
                {
                    var vm = userControl.DataContext as ViewModelBase;
                    vm?.Refresh("yololo");

                    ct.ThrowIfCancellationRequested();

                }));
            }
        }
        catch(Exception e)
        {
            //Do nothing
        }
    }, 
    ct);

    _manageErrorTask = Tuple.Create(task, token);
}


0 个答案:

没有答案