Task.Factory.StartNew()或Task.Run()正确用法?

时间:2016-04-07 17:44:24

标签: c# multithreading task-parallel-library

我是多线程的新手,我很难理解用任务完成任务的所有方法。我试图在一个大程序中实现它,但没有人想要无缘无故地查看所有数千行处理代码,所以我编写了一个简单的测试程序,使用Sleep()而不是真正的工作并使其变得非常简单

问题是最底层的。

using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            BlockingCollection<int> col = new BlockingCollection<int>();
            for(int z = 0; z<=50; z++)
            {
                col.Add(z);
            }

            Console.WriteLine("Hi from main! ThreadID: {0}", Thread.CurrentThread.ManagedThreadId);
            var parent = Task.Factory.StartNew(() =>
            {
                Console.WriteLine("Hi from PARENT! ThreadID: {0}", Thread.CurrentThread.ManagedThreadId);
                foreach (int num in col.GetConsumingEnumerable())
                {
                        Thread.Sleep(100);
                        Task.Factory.StartNew(() =>
                        {
                            Thread.Sleep(num*100);
                            if (num == 50)
                            {
                                col.CompleteAdding(); //kick out of the foreach loop
                                Thread.Sleep(25000);
                            }
                            Console.WriteLine("Hi from a Child! ThreadID: {0}", Thread.CurrentThread.ManagedThreadId);

                        }, TaskCreationOptions.AttachedToParent);
                }
                Console.WriteLine("Parent done making children. ThreadID: {0}", Thread.CurrentThread.ManagedThreadId);
            }, TaskCreationOptions.LongRunning);

            var final = parent.ContinueWith((antecedent) =>
            {
                Console.WriteLine("DONE!");
            },TaskContinuationOptions.OnlyOnRanToCompletion
                );

            Console.WriteLine("Calling Wait on final. ThreadID: {0}", Thread.CurrentThread.ManagedThreadId);
            final.Wait();
            Console.ReadLine();
        }
    }
}

代码将51个元素添加到阻塞集合中,然后启动一个名为Parent的任务。 Parent使用阻塞集合中的项目,直到标记为CompleteAdding()为止。

父任务是长期运行的,因为我不希望它从线程池中拉出线程。然后它应该产生附加的子任务,这些任务将睡眠一段时间,如果该元素是50&#39;它调用CompleteAdding()

然后有一个名为final的延续,只有在父项运行完成时才会运行。如果完成阻塞集合并且所有子任务也完成,则父级只能完成。

然后我从main调用final.Wait()(在我的真实程序中,final.Wait()可能会使用OnFormClosing()方法。)

完成所有这一切的重点是能够在程序关闭之前确保所有当前正在运行的工作都已完成,并且所有排队的工作也已完成。

这就是问题所在。我在很多地方都看到我应该使用Task.Run()代替Task.Factory.StartNew(),所以我尝试将它们更改出去,我开始收到错误说Error CS1643 Not all code paths return a value in lambda expression of type 'Func<Task>'如果我不知道为什么我需要返回值# 39;想要回报。也正确使用Task.Factory.StartNew()或我做了冒险/危险的事情吗?

note 不确定是否重要但在程序中我将在睡眠中使用此设置,例如匹配数据并将其发送到oracle db。我们也不能高于.NET 4.6

2 个答案:

答案 0 :(得分:0)

Microsoft的文档将Task.Run描述为异步运行任务的“更简单方法”。它和Task.Factory.StartNew都返回Task,语法相同。我有兴趣看到给你编译错误的代码。但是,如果您的代码与Task.Factory.StartNew一起使用,我认为没有令人信服的理由进行更改。

        Task.Run(() =>
        {
            Console.Write("Doing");
            Console.Write("Something");
        });

        Task.Factory.StartNew(() =>
        {
            Console.Write("Doing");
            Console.Write("Something");
        });

答案 1 :(得分:0)

让我们简化代码的DF = data.frame(int = 1:10, float = rnorm(10), cur = rnorm(10) * 1E5, lrg = rnorm(10) * 1E8, pct = rnorm(10)) rhandsontable(DF, width = 550, height = 300) %>% hot_cols(renderer = " function (instance, td, row, col, prop, value, cellProperties) { Handsontable.renderers.TextRenderer.apply(this, arguments); if (row == 2){ td.style.background = 'lightyellow'; }}") %>% hot_col("float", format = "0.0") %>% hot_col("cur", format = "$0,0.00") %>% hot_col("lrg", format = "0a") %>% hot_col("pct", format = "0%") 版本:

Task.Run

此代码错误:there is no overload of Task.Run() accepting TaskCreationOptions。但是C#编译器报告的错误消息(&#34;并非所有代码路径都返回类型&#39; Task.Run(() => { }, TaskCreationOptions.LongRunning); &#39;&#34;)的lambda表达式中的值也是错误的。我认为这是C#编译器中的一个错误,所以I reported it