Note that there are some explanatory texts on larger screens.

plurals
  1. PORe-factor a ThreadPool.QueueUserWorkItem to Task Parallel Library
    primarykey
    data
    text
    <p>Trying to re-factor a ThreadPool.QueueUserWorkItem to TPL and to be honest I don't know either very well (yet). </p> <p>In real life this will be an I/O operation. Query to Azure Table Storage on the PartitionKey so it should parallel effectively.</p> <p>See the method GetAllTPL() as it has the simple TPL I wrote. It passes this very simple test case. Is the TPL wrong and I just don't know it? Can I do that better? Anything that might make this simple test case fail when it is an actual Table query? </p> <p>ThreadPool.QueueUserWorkItem and TPL both produce the same correct answer for this very limited test case. Put stopwatch on a bigger (but still simplified) test case and TPL is just short of twice as fast as ThreadPool.QueueUserWorkItem. TPL seems to queue up in groups of 3 and ThreadPool.QueueUserWorkItem in groups of 2 running on just a P4 with hyper threading. Since thread.sleep is not real work that does not tell me a lot.</p> <p>The ThreadPool.QueueUserWorkItem is from a .NET 3.5 code sample (pre TPL). I am pretty sure TPL has a better option but I am new to TPL. Thanks</p> <pre><code>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&lt;string&gt; 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&lt;string&gt; GetAllQWI(string[] partitionKey) { // this a a code sample from .NET 3.5 and it runs on 4.0 IEnumerable&lt;string&gt; finalResults = null; ManualResetEvent[] resetEvents = new ManualResetEvent[partitionKey.Length]; HashSet&lt;string&gt;[] rowKeys = new HashSet&lt;string&gt;[partitionKey.Length]; for (int i = 0; i &lt; rowKeys.Length; i++) { resetEvents[i] = new ManualResetEvent(false); ThreadPool.QueueUserWorkItem(new WaitCallback((object index) =&gt; { 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&lt;string&gt;)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&lt;string&gt; GetAllTPL(string[] partitionKey) { // this is the conversion of the ThreadPool.QueueUserWorkItem to TPL // seems to be working but is this optimal IEnumerable&lt;string&gt; finalResults = null; HashSet&lt;string&gt;[] rowKeys = new HashSet&lt;string&gt;[partitionKey.Length]; // how to do this in TPL Parallel.For(0, partitionKey.Length, i =&gt; { 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&lt;string&gt;)rowKeys[0]; foreach (var thisRowKeys in rowKeys) { finalResults = finalResults.Intersect(thisRowKeys); } return finalResults; } public static HashSet&lt;string&gt; 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&lt;string&gt; { "alph", "beta", "gamma", "delta" }; } else { return new HashSet&lt;string&gt; { "beta", "gamma", "delta", "epsilon" }; } } } } </code></pre> <p>Spent several hours to get this far. If TPL will do this then I will learn more about TPL and not learn ThreadPool.QueueUserWorkItem. It kind of scares me the TPL was so simple. Just want to check that I am not missing something. I got this TPL from a compute intensive sample. </p> <p>One post on SO about irregular results with TPL and Azure but in the end could not reproduce. <a href="https://stackoverflow.com/questions/3664083/can-parallel-foreach-be-used-safely-with-cloudtablequery">Can Parallel.ForEach be used safely with CloudTableQuery</a> </p> <p>Another post from the Azure team states TPL and Azure is OK <a href="https://stackoverflow.com/questions/3056628/windows-azure-parallelization-of-the-code">Windows Azure: Parallelization of the code</a></p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload