Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 将ThreadPool.QueueUserWorkItem重新分解为任务并行库_.net_Task Parallel Library_Azure Table Storage - Fatal编程技术网

.net 将ThreadPool.QueueUserWorkItem重新分解为任务并行库

.net 将ThreadPool.QueueUserWorkItem重新分解为任务并行库,.net,task-parallel-library,azure-table-storage,.net,Task Parallel Library,Azure Table Storage,试图将ThreadPool.QueueUserWorkItem重新分解为TPL,老实说,我也不太清楚(目前) 在现实生活中,这将是一个I/O操作。查询分区键上的Azure表存储,以便它能够有效地并行 查看GetAllTPL()方法,因为它具有我编写的简单TPL。它通过了这个非常简单的测试用例。第三方物流是不是错了,我就是不知道?我能做得更好吗?当这个简单的测试用例是一个实际的表查询时,有什么可能使它失败的吗 对于这个非常有限的测试用例,ThreadPool.QueueUserWorkItem和T

试图将ThreadPool.QueueUserWorkItem重新分解为TPL,老实说,我也不太清楚(目前)

在现实生活中,这将是一个I/O操作。查询分区键上的Azure表存储,以便它能够有效地并行

查看GetAllTPL()方法,因为它具有我编写的简单TPL。它通过了这个非常简单的测试用例。第三方物流是不是错了,我就是不知道?我能做得更好吗?当这个简单的测试用例是一个实际的表查询时,有什么可能使它失败的吗

对于这个非常有限的测试用例,ThreadPool.QueueUserWorkItem和TPL都会生成相同的正确答案。将秒表放在一个更大(但仍然简化)的测试用例上,TPL的速度只有ThreadPool.QueueUserWorkItem的两倍。TPL似乎以3人一组的方式排队,而ThreadPool.QueueUserWorkItem则以2人一组的方式排队,只在一个具有超线程的P4上运行。因为thread.sleep不是真正的工作,它不会告诉我很多

ThreadPool.QueueUserWorkItem来自.NET 3.5代码示例(TPL之前)。我很确定TPL有更好的选择,但我对TPL是新手。谢谢

using System.Threading;
using System.Threading.Tasks;

namespace WaitForConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] partitionKey = new string[] { "one", "two", "three", "four" };
            IEnumerable<string> commonRowKeys = GetAllQWI(partitionKey);          
            foreach (string commonRowKey in commonRowKeys) Console.WriteLine(commonRowKey);
            Console.ReadLine();
            commonRowKeys = GetAllTPL(partitionKey);
            foreach (string commonRowKey in commonRowKeys) Console.WriteLine(commonRowKey);
            Console.ReadLine();
        }

        public static IEnumerable<string> GetAllQWI(string[] partitionKey)
        {
            // this a a code sample from .NET 3.5 and it runs on 4.0
            IEnumerable<string> finalResults = null;
            ManualResetEvent[] resetEvents = new ManualResetEvent[partitionKey.Length];
            HashSet<string>[] rowKeys = new HashSet<string>[partitionKey.Length];
            for (int i = 0; i < rowKeys.Length; i++)
            {
                resetEvents[i] = new ManualResetEvent(false);
                ThreadPool.QueueUserWorkItem(new WaitCallback((object index) =>
                {
                    Console.WriteLine("GetAllQWI " + ((int)index).ToString());
                    rowKeys[(int)index] = TableQueryGetRowKeys(partitionKey[(int)index]);
                    resetEvents[(int)index].Set();
                }), i);
            }
            try
            {
                WaitHandle.WaitAll(resetEvents);
                Console.WriteLine("WaitAll done");
                finalResults = (IEnumerable<string>)rowKeys[0];
                foreach (var thisRowKeys in rowKeys)
                {
                    finalResults = finalResults.Intersect(thisRowKeys);
                }

            }
            catch (Exception ex)
            {
                Console.WriteLine("WaitAll ex " + ex.Message);
            }
            return finalResults;
        }

        public static IEnumerable<string> GetAllTPL(string[] partitionKey)
        {
            // this is the conversion of the ThreadPool.QueueUserWorkItem to TPL 
            // seems to be working but is this optimal
            IEnumerable<string> finalResults = null;
            HashSet<string>[] rowKeys = new HashSet<string>[partitionKey.Length];
            //  how to do this in TPL
            Parallel.For(0, partitionKey.Length, i =>
            {
                Console.WriteLine("GetAllTPL " + i.ToString());
                rowKeys[i] = TableQueryGetRowKeys(partitionKey[i]);
            }); 
            //  Do I need to do anything special to wait for all the tasks to finish?
            //  Interesting that i is not necessarily in order but it does not need to be
            finalResults = (IEnumerable<string>)rowKeys[0];
            foreach (var thisRowKeys in rowKeys)
            {
                finalResults = finalResults.Intersect(thisRowKeys);
            }
            return finalResults;
        }

        public static HashSet<string> TableQueryGetRowKeys(string partitionKey)
        {
            // in real life this is an Azure table query to get all rowKeys for a partitionKey
            Thread.Sleep(10000);
            if (DateTime.Now.Millisecond % 2 == 0)
            {
                return new HashSet<string> { "alph", "beta", "gamma", "delta" };
            }
            else
            {
               return new HashSet<string> { "beta", "gamma", "delta", "epsilon" };
            }
        }
    }
}
使用系统线程;
使用System.Threading.Tasks;
命名空间WaitForConsole
{
班级计划
{
静态void Main(字符串[]参数)
{
string[]partitionKey=新字符串[]{“一”、“二”、“三”、“四”};
IEnumerable CommonRowKey=GetAllQWI(分区键);
foreach(commonRowKey中的字符串commonRowKey)控制台.WriteLine(commonRowKey);
Console.ReadLine();
commonRowKeys=GetAllTPL(分区键);
foreach(commonRowKey中的字符串commonRowKey)控制台.WriteLine(commonRowKey);
Console.ReadLine();
}
公共静态IEnumerable GetAllQWI(字符串[]分区键)
{
//这是一个来自.NET3.5的代码示例,它在4.0上运行
IEnumerable finalResults=null;
ManualResetEvent[]resetEvents=新的ManualResetEvent[partitionKey.Length];
HashSet[]行键=新的HashSet[partitionKey.Length];
for(int i=0;i
{
WriteLine(“GetAllQWI”+((int)index.ToString());
rowKeys[(int)index]=TableQueryGetRowKeys(partitionKey[(int)index]);
重置事件[(int)索引].Set();
}),i);
}
尝试
{
WaitHandle.WaitAll(重置事件);
控制台。写入线(“等待全部完成”);
最终结果=(IEnumerable)行键[0];
foreach(在rowKeys中的var thisRowKeys)
{
finalResults=finalResults.Intersect(thisRowKeys);
}
}
捕获(例外情况除外)
{
Console.WriteLine(“WaitAll-ex”+ex.Message);
}
返回最终结果;
}
公共静态IEnumerable GetAllTPL(字符串[]分区键)
{
//这是ThreadPool.QueueUserWorkItem到TPL的转换
//似乎是工作,但这是最佳的
IEnumerable finalResults=null;
HashSet[]行键=新的HashSet[partitionKey.Length];
//如何在第三方物流中做到这一点
Parallel.For(0,partitionKey.Length,i=>
{
Console.WriteLine(“GetAllTPL”+i.ToString());
rowKeys[i]=表查询关键字(partitionKey[i]);
}); 
//我需要做什么特殊的事情来等待所有的任务完成吗?
//有趣的是,我不一定是有序的,但也不一定是有序的
最终结果=(IEnumerable)行键[0];
foreach(在rowKeys中的var thisRowKeys)
{
finalResults=finalResults.Intersect(thisRowKeys);
}
返回最终结果;
}
公共静态哈希集表QueryGetRowKeys(字符串分区键)
{
//在现实生活中,这是一个Azure表查询,用于获取partitionKey的所有行键
睡眠(10000);
如果(DateTime.Now.毫秒%2==0)
{
返回新的哈希集{“alph”、“beta”、“gamma”、“delta”};
}
其他的
{
返回新的哈希集{“beta”、“gamma”、“delta”、“epsilon”};
}
}
}
}
花了几个小时才走到这一步。如果TPL将这样做,那么我将了解更多关于TPL的信息,而不是了解ThreadPool.QueueUserWorkItem。我有点害怕TPL太简单了。我只是想确认我没有遗漏什么。我从一个计算密集型样本中得到了这个TPL

一篇关于TPL和Azure的不规则结果的帖子,但最终无法重现


Azure团队的另一篇帖子称,TPL和Azure是可以的

您希望如何将您不理解的代码重构为您不理解的新代码?即使我们为您重构它,您将如何维护它?@RobertHarvey几乎所有关于SO的问题都来自于一个知识为零到部分的人。这不是生产代码,我不希望这样来维护生产代码。
几乎所有关于生产代码的问题都来自于一个不了解生产代码的人。
——这种说法显然是错误的。我们希望人们带着一些知识来到这里。如果您是在零知识的框架下提问,那么最好的方法是阅读ThreadPool和TPL,如果您陷入困境,请在这里提问。