2011-02-10 6 views
11

To jest "jest to możliwe, a jeśli tak, czy możesz dać mi szybki przykład, ponieważ nie mogę znaleźć jednego w Internecie?" rodzaj pytania.Czy biblioteka równoległa do zadania .NET 4 może korzystać z obiektów COM?

Mam kilka całkowicie oddzielnych (tj. "Zawstydzająco równoległych") procesów, które chcę uruchomić równolegle przy użyciu biblioteki zadań równoległych w .NET Framework 4 przy użyciu C#. Niektóre z tych procesów wymagają użycia oprogramowania, do którego można uzyskać dostęp za pośrednictwem automatyzacji COM/OLE.

W szczególności istnieje pętla Parallel.Foreach(), która dzieli zadania z listy elementów, zasadniczo wywołując inną funkcję wewnątrz Parallel.Foreach w celu obsługi przetwarzania (więc niektóre z tych funkcji wykorzystują biblioteki COM do praca).

Czy to możliwe? Dzięki.

+4

Brzmi jak idealny kandydat do szybkiego testu ... spróbuj. – Oded

Odpowiedz

18

Jest w 100% możliwe korzystanie z obiektów COM z licencją OC. Chociaż prawdą jest, że domyślnie TPL korzysta ze standardowego .NET ThreadPool, TPL ma punkt rozszerzenia za pośrednictwem the TaskScheduler class, który umożliwia ci dostarczenie własnego harmonogramu, który może wysłać pracę do wątków, które stworzyłeś.

W przypadku korzystania z obiektów COM najpierw trzeba wiedzieć, czy klasa COM wymaga gwintowania STA lub gwintowania MTA. Jeśli chodzi o wątki MTA, to nie ma nic szczególnego, co trzeba zrobić, ponieważ klasa COM może już być używana z dowolnego losowego wątku. Niestety, większość klasycznych obiektów COM zwykle opiera się na wątkach STA i wtedy trzeba użyć niestandardowego TaskScheduler, aby każdy wątek .NET, z którego je używasz, był initialized as an STA compatible thread.

Podczas gdy TaskSchedulers nie są dość proste do napisania, nie są tak trudne do napisania, jeśli masz podstawową wiedzę na temat wątków. Na szczęście the ParallelExtensions Extras library zapewnia już klasę StaTaskScheduler, więc nie musisz nawet pisać nic samemu. Zespół PFX omawia implementację i niektóre przypadki użycia dla klasy StaTaskScheduler, która jest a great blog post here.

Zasadniczo, należy zainicjować nowy StaTaskScheduler jako statyczny w dowolnym miejscu na jednej z klas, a następnie po prostu rozpocząć Tasks określając, że są one zaplanowane przez tę instancję. To wyglądałoby mniej więcej tak:

// 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); 
+0

Bardzo interesujące, będę musiał się w to zagłębić, dzięki! Dla porównania podstawową funkcją, którą próbuję osiągnąć, jest równoległe wykonanie kilku przepływów pracy w R (http://www.r-project.org/). Opowiem o tym tutaj, jeśli coś wymyślę. – user483679

+0

Dzięki, dokładnie to, czego potrzebowałem. –

2

Jest to potencjalnie możliwe, ale może również nie działać.

Wiele obiektów COM wymaga określonego apartment threading. Podczas korzystania z Parallel.For/ForEach, używasz .NET ThreadPool, który nie ma instalacji threadingu mieszkania. To może działać i może dla niektórych obiektów COM, ale może również powodować awarie i dziwne wyjątki COM, które są trudne do wyśledzenia.

0

Kilka dodatkowych informacji, które jeszcze muszę zweryfikować, ale które mogą być pomocne. Domyślny harmonogram zadań użyje bieżącego wątku do wykonania niektórych prac, a następnie, w razie potrzeby, doda dodatkowe wątki z puli wątków.

Może to powodować problemy w przypadku współdzielenia obiektu COM podczas wykonywania polecenia Parallel.ForEach. Na przykład załóżmy, że twoim głównym wątkiem jest STA. Tworzysz obiekt COM na tym i używasz Parallel.ForEach do wykonania pracy, w której każdy wątek próbuje uzyskać dostęp do wcześniej utworzonego obiektu COM. Podejrzewam, że to się zepsuje, a wstępne testy zdają się to potwierdzać.W tym scenariuszu widzę co najmniej kilka opcji:

  • Zakładając, że obiekt COM obsługuje MTA, użyj wątku wywołującego, używając MTA. Jednak może to nie być możliwe z innych powodów. Na przykład, jeśli aplikacja jest aplikacją Windows Forms, uważam, że funkcja Main() jest wymagana do posiadania atrybutu STAThread.
  • Użyj alternatywnego harmonogramu zadań, takiego jak StaTaskScheduler wymieniony przez Drew. Możesz mieć wszystkie wątki STA lub użyć programu planującego, który nie używa wątku wywołującego i uruchamiać wszystkie wątki MTA.
Powiązane problemy