首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有反馈对话框助手类的任务

带有反馈对话框助手类的任务
EN

Code Review用户
提问于 2016-01-29 13:08:45
回答 1查看 502关注 0票数 2

我目前正在一个Windows.Forms项目中工作,在这个项目中,我需要在任务运行时显示一个响应性的反馈表单,这是非常常见的。这些任务通常需要5到10秒左右才能完成,在任务成功完成或失败之前,用户无法做任何其他事情。

为了保持UI响应性,我编写了一个小助手类。我对任务和异步编程环境非常陌生,所以我不确定我是在这里过火还是走错了方向:

这是一个小助手类:

代码语言:javascript
复制
internal sealed class TaskManagerWithFeedbackDialog<TController> where TController : IViewController, new() 
{
    public static Task<TReturn> RunTask<TReturn>(Func<TReturn> func)
    {
        if (func == null)
        {
            throw new ArgumentNullException("func");
        }

        var manager = new _AsyncTaskManager<TReturn>(func);

        using (var view = new TController())
        {
            var task = manager.Start(view);
            view.ShowViewDialog();
            return task;
        }
    }

    private class _AsyncTaskManager<T>
    {
        private readonly Func<T> taskFunc;

        public _AsyncTaskManager(Func<T> func)
        {
            taskFunc = func;
        }

        public Task<T> Start(IViewController feedBackView)
        {
            var task = Task.Factory.StartNew(taskFunc);

            task.ContinueWith(t =>
            {
                feedBackView.CloseView();
            }, TaskContinuationOptions.OnlyOnFaulted);

            task.ContinueWith(t =>
            {
                feedBackView.CloseView();
                return t.Result;
            }, TaskContinuationOptions.NotOnFaulted);

            return task;
        }
    }
}

IViewController.CloseView()的实现如下所示:

代码语言:javascript
复制
public virtual void CloseView()
{
    if (View.InvokeRequired)
    {
        View.Invoke(new Action(View.Close));
    }
    else
    {
        View.Close();
    }
}

另一个我不确定的问题是,处理ArregateException的最佳地点在哪里?现在我不处理任何事情,因为如果任务失败,我不需要清理任何东西。我只需检查返回的任务是否有任何错误。这样做对吗?异步任务总是“默默地”失败吗?如果我需要清理,它会在哪里?在.ContinueWith( .... , TaskContinuationOptions.OnlyOnFaulted)里面?

EN

回答 1

Code Review用户

发布于 2016-01-31 03:21:04

这里更新的是一些清理。现在,您可以在阻塞开始之前返回对Task<T>的引用:TaskWithFeedback.Run()是一个非阻塞调用。它还与视图中的Form.Show()Form.ShowModel()一起工作。

代码语言:javascript
复制
class TaskWithFeedback<TViewController> 
    where TViewController : IViewController, new()
{
    public static async Task<T> Run<T>(Func<T> function)
    {
        var context = TaskScheduler.FromCurrentSynchronizationContext();
        var view = new TViewController();
        var opening = new Task(view.ShowViewDialog);
        opening.Start(context);
        var task = Task.Run(function);
        var closing = task
            .ContinueWith(t => view.CloseViewDialog(), context);                

        try
        {                             
            return await task;
        }
        finally
        {
            await opening;
            await closing;
        }
    }
}

示例:

代码语言:javascript
复制
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private async void button1_Click(object sender, EventArgs e)
    {
        Text = await TaskWithFeedback<Form2>.Run(() =>
            {
                Thread.Sleep(3000);
                return "Hello!";
            });            
    }   
}

class Form2 : Form, IViewController
{
    public void ShowViewDialog() => ShowDialog();
    public void CloseViewDialog() => Close();
}
票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/118248

复制
相关文章

相似问题

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