By user483679


2011-02-10 21:47:33 8 Comments

This is an "is this possible, and if so can you give me a quick example because I can't find one online?" kind of question.

I have a number of completely separate (i.e. "embarrassingly parallel") processes that I want to run in parallel using the Task Parallel library in .NET Framework 4 using C#. Some of these processes require the use of software that can be accessed via COM/OLE automation.

Specifically, there is a Parallel.Foreach() loop that divides up the tasks from a list of items, basically calling a different function inside the Parallel.Foreach to handle the processing (so some of these functions employ COM libraries to work).

Is this possible? Thanks.

3 comments

@Phil Haselden 2012-07-02 04:31:23

Some additional information that I am yet to verify, but that may be helpful. The default task scheduler will use the current thread to do some of the work then add additional threads from the thread pool as necessary.

This could cause problems if you are sharing a COM object when doing Parallel.ForEach. For example, let's say your main thread is STA. You instantiate the COM object on that and use Parallel.ForEach to do some work where each thread tries to access the previously instantiated COM object. I suspect that it will break, and initial testing seems to back this up. In this scenario I see at least a couple of options:

  • Assuming the COM object supports MTA, have the calling thread use MTA. However this may not be an option for other reasons. For example, if the application is a Windows Forms application I believe Main() is required to have the STAThread attribute.
  • Use an alternative task scheduler such as the StaTaskScheduler mentioned by Drew. You could either have all STA threads or use a scheduler that does not use the calling thread and run all MTA threads.

@Drew Marsh 2011-02-12 17:31:56

It's 100% possible to use COM objects with the TPL. While it's true that, by default, the TPL will use the standard .NET ThreadPool, the TPL has an extension point via the TaskScheduler class which enables you to provide your own scheduler which can dispatch work to threads which you've created.

In the case of of using COM objects you first need to know if the COM class requires STA threading or MTA threading. If MTA threading, then there's nothing special that needs to be done because the COM class can already be used from any random thread. Unfortunately most classic COM objects tend to rely on STA threading and that's when you'd need to employ a custom TaskScheduler so that whatever .NET thread you're using them from has been initialized as an STA compatible thread.

While TaskSchedulers are not exactly trivial to write, they're not really that hard to write either if you've got a basic understanding of threading. Luckily the ParallelExtensions Extras library already provides an StaTaskScheduler class so you don't even need to write anything yourself. There's a great blog post here by the PFX team that discusses the implementation of and some use cases for the the StaTaskScheduler class.

Basically though, you'll want to initialize a new StaTaskScheduler as a static somewhere on one of your classes and then just start your Tasks specifying that they are scheduled by that instance. That would look something like this:

// Create a static instance of the scheduler specifying some max number of threads
private static readonly StaTaskScheduler MyStaTaskScheduler = new StaTaskScheduler(4);

....

// Then specify the scheduler when starting tasks that need STA threading
Task.TaskFactory.StartNew(
() =>
{
    MyComObject myComObject = new MyComObject();

    myComObject.DoSomething();

    // ... etc ...
},
CancellationToken.None,
TaskCreationOptions.None,
MyStaTaskScheduler);

@user483679 2011-02-14 00:52:21

Very interesting, I will have to look into this, thanks! For reference the primary functionality I am trying to achieve is the parallel execution of several workflows in R (r-project.org). I'll report back here if I figure anything out.

@net_prog 2012-10-03 14:58:29

Thanks, exactly what I needed.

@Reed Copsey 2011-02-10 21:59:33

It's potentially possible, but it may also not work.

Many COM objects require a specific apartment threading. When you use Parallel.For/ForEach, you're running on the .NET ThreadPool, which doesn't have the apartment threading setup. This may work, and can for some COM objects, but can also cause crashes and strange COM exceptions that are difficult to track down.

Related Questions

Sponsored Content

25 Answered Questions

[SOLVED] How can I get the application's path in a .NET console application?

3 Answered Questions

3 Answered Questions

0 Answered Questions

Task Parallel Library Task.ContinueWith using C++/CLI

1 Answered Questions

Parallel Tasks not waiting

3 Answered Questions

[SOLVED] C# parallel foreach equally finishing tasks

1 Answered Questions

[SOLVED] Release "ownership" of COM object in .NET

  • 2012-05-02 16:16:25
  • sxthomson
  • 270 View
  • 6 Score
  • 1 Answer
  • Tags:   c# vb.net com

1 Answered Questions

1 Answered Questions

[SOLVED] Help with Task parallel library usage

1 Answered Questions

Sponsored Content