TPL 问题、错误处理和返回值

发布于 2024-10-08 13:42:55 字数 2916 浏览 0 评论 0原文

我花了几个小时尝试实现这样的场景,但带有输入参数和返回值。

这工作正常,我得到了我所期望的:

public class AsyncStuff2
{
    public void DoAsyncStuff()
    {            
        TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();

        Task myTask = Task.Factory.StartNew(() =>
        {
            OperationXy();
        });

        bool hadError = false;

        myTask = myTask.ContinueWith(errorTest =>
        {
            Console.WriteLine("Faulted");
            hadError = true;

            if (errorTest.Exception != null)
            {
                Console.WriteLine(errorTest.Exception.Message);
            }
        }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, uiScheduler);

       myTask.ContinueWith(another =>
        {
            Console.WriteLine("Done");

            if (hadError)
            {
                Console.WriteLine("...but with error");
            }

        }, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, uiScheduler);

    }

    private void OperationXy()
    {
        Console.WriteLine("OperationXY");
        throw new ArgumentException("Just for Test");
    }

输出将是这样的:

OperationXY 有缺陷 发生一个或多个错误。 完毕 ...但是有错误

但是当我修改这个示例时,任务继续不再像我一样工作:

public class AsyncStuff
{

    public string Path { get; set; }

    public void DoAsyncStuff()
    {
        Path = "A Input...";

        TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();

        Task<string> myTask = Task<string>.Factory.StartNew((input) =>
        {
            return OperationXy(Path);

        }, Path, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);

        bool hadError = false;

        myTask = myTask.ContinueWith<string>(errorTest =>
        {
            Console.WriteLine("Faulted");
            hadError = true;

            if (errorTest.Exception != null)
            {
                Console.WriteLine(errorTest.Exception.Message);
            }

            return null;

        }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, uiScheduler);

        myTask.ContinueWith(another =>
        {
            Console.WriteLine("Done, Result: {0}", myTask.Result);

            if (hadError)
            {
                Console.WriteLine("...but with error");
            }

        }, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, uiScheduler);
    }

    private string OperationXy(string returnThat)
    {
        Console.WriteLine("OperationXY, Input ({0})", returnThat);

        //throw new ArgumentException("Just for Test");

        return returnThat;
    }

}

我想要实现的是:

  • 将处理所需的输入传递给任务
  • 将结果设置为 UI 元素
  • 处理错误,但无论如何继续“OnlyOnRanToCompletion”

任何帮助表示

谢谢马丁

感谢,

I'm trying for hours to implement a scenario like this, but with input parameters and a return value.

This works fine and I get what I expect:

public class AsyncStuff2
{
    public void DoAsyncStuff()
    {            
        TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();

        Task myTask = Task.Factory.StartNew(() =>
        {
            OperationXy();
        });

        bool hadError = false;

        myTask = myTask.ContinueWith(errorTest =>
        {
            Console.WriteLine("Faulted");
            hadError = true;

            if (errorTest.Exception != null)
            {
                Console.WriteLine(errorTest.Exception.Message);
            }
        }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, uiScheduler);

       myTask.ContinueWith(another =>
        {
            Console.WriteLine("Done");

            if (hadError)
            {
                Console.WriteLine("...but with error");
            }

        }, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, uiScheduler);

    }

    private void OperationXy()
    {
        Console.WriteLine("OperationXY");
        throw new ArgumentException("Just for Test");
    }

Output will be this:

OperationXY
Faulted
One or more errors occurred.
Done
...but with error

But when I modify this example, task continuation does not work as i except anymore:

public class AsyncStuff
{

    public string Path { get; set; }

    public void DoAsyncStuff()
    {
        Path = "A Input...";

        TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();

        Task<string> myTask = Task<string>.Factory.StartNew((input) =>
        {
            return OperationXy(Path);

        }, Path, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);

        bool hadError = false;

        myTask = myTask.ContinueWith<string>(errorTest =>
        {
            Console.WriteLine("Faulted");
            hadError = true;

            if (errorTest.Exception != null)
            {
                Console.WriteLine(errorTest.Exception.Message);
            }

            return null;

        }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, uiScheduler);

        myTask.ContinueWith(another =>
        {
            Console.WriteLine("Done, Result: {0}", myTask.Result);

            if (hadError)
            {
                Console.WriteLine("...but with error");
            }

        }, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, uiScheduler);
    }

    private string OperationXy(string returnThat)
    {
        Console.WriteLine("OperationXY, Input ({0})", returnThat);

        //throw new ArgumentException("Just for Test");

        return returnThat;
    }

}

What I want to achieve is:

  • Passing an input which is required for processing to a task
  • Set the result to a UI Element
  • Handling error, but continue to "OnlyOnRanToCompletion" anyway

Any help appreciated

Thanks

Martin

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

明天过后 2024-10-15 13:42:55

这是因为您的代码中有错误。您在创建错误处理延续时重新定义 myTask。该行:

        myTask = myTask.ContinueWith(errorTest =>

应该读为:

        myTask.ContinueWith(errorTest =>

否则,您将把 ran to finish 延续添加到错误处理延续中,而不是添加到原始 myTask 中。

这应该可以修复您的代码。现在输出应为:

OperationXY 
Done

This is because your code has a bug in it. You redefine myTask in your creation of the error handling continuation. The line:

        myTask = myTask.ContinueWith(errorTest =>

Should read:

        myTask.ContinueWith(errorTest =>

Otherwise you are adding the ran to completion continuation to the error handling continuation, not to the original myTask.

This should fix your code. The output should now read:

OperationXY 
Done
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文