首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于TPL的循环服务:正确的工作者方法签名,异步

基于TPL的循环服务:正确的工作者方法签名,异步
EN

Stack Overflow用户
提问于 2018-07-13 13:13:09
回答 1查看 51关注 0票数 1

关于正确的worker方法签名,我需要理解以下几点:

  • 返回Task而不是void for Worker方法是否有意义(如果要同步的话)?
  • 我真的应该等待(调用Wait()) Worker方法(如果要同步)吗?
  • 当标记为返回Worker对象时,Task方法的返回值应该是什么(如果进行同步/异步)?
  • 如果Worker方法完成的工作是长时间运行的CPU/IO绑定工作,那么它应该是什么签名和主体?我应该遵循2.本建议 (如果是混合/异步)吗?

Note

尽管使用了cpu绑定代码,但还是可以选择调用io绑定方法的异步版本(sql查询)。所以它可能是同步的,也可能是部分异步的。至于Worker方法中代码的性质。

代码语言:javascript
复制
public class LoopingService
{
    private CancellationTokenSource cts;
    // ..

    void Worker(CancellationToken cancellationToken)
    {
        while(!cancellationToken.IsCancellationRequested)
        {
            // mixed, CPU/IO-bound code

            try {
                // sql query (can be called either as sync/async)
                var lastId = documentService.GetLastDocument().Id;

                // get next document from a public resource (third-party code, sync)
                // can be moved to a web api
                var document = thirdPartyDocumentService.GetNextDocument(lastId);

                // apply different processors in parallel
                var tasksList = new List<Task>();

                foreach(var processor in documentService.Processors) {
                    // each processor checks if it's applicable
                    // which may include xml-parsing, additional db calls, regexes
                    // if it's applicable then document data is inserted into the db
                    var task = new Task(() => processor.Process(document));
                    tasksList.Add(task);
                    task.Start();
                }

                // or 
                // var tasksList = documentService.ProcessParallel(document);

                Task.WaitAll(tasksList.ToArray(), cancellationToken);
            }
            catch(Exception ex) {
                logger.log(ex);
            }
        }  
    }

    public void Start()
    {
        this.cts = new CancellationTokenSource();
        Task.Run(() => this.Worker(cts.Token));
    }

    public void Stop()
    {
        this.cts.Cancel();
        this.cts.Dispose();
    }

}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-07-13 13:47:11

返回任务而不是为Worker方法返回方法有意义吗?

如果Worker是一个真正的异步方法,它应该返回一个Task,以便您能够等待它。如果它只是在后台线程上运行的同步方法,则没有必要从void中更改返回类型,前提是该方法不应该返回任何内容。

当标记为返回Worker对象时,Task方法的返回值应该是多少?

没什么。如果该方法是异步的,并使用返回类型的async标记为Task,则不应该返回任何值:

代码语言:javascript
复制
async Task Worker(CancellationToken cancellationToken) { ... }

注意,除非在方法中实际使用await关键字,否则没有必要将该方法定义为await

Worker方法的哪些特征和主体应该给出它所完成的工作是长时间运行的CPU/IO绑定工作?我应该遵循这个建议吗?

是的,可能吧。如果出于某种原因,您在同一方法中同时执行异步和同步(CPU绑定)工作,则应该更喜欢使用异步签名,而不是将同步内容包装在Task.Run中。那么您的服务将会是这样的:

代码语言:javascript
复制
public class LoopingService
{
    private CancellationTokenSource cts;

    async Task Worker(CancellationToken cancellationToken)
    {
        while (!cancellationToken.IsCancellationRequested)
        {
            await ...
        }
    }

    public async Task Start()
    {
        this.cts = new CancellationTokenSource();
        await this.Worker(cts.Token).ConfigureAwait(false);
    }

    public void Stop()
    {
        this.cts.Cancel();
        this.cts.Dispose();
    }

}

理想情况下,您的方法应该是异步的或CPU绑定的,但不能两者兼而有之。

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

https://stackoverflow.com/questions/51325998

复制
相关文章

相似问题

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