MainThread在执行与COM交互的任务时阻塞

时间:2012-03-07 13:54:40

标签: c# winforms com task blocking

我想在C#gui应用程序中执行一些持久的任务(基于Windows窗体)。 我首先尝试与Task.Factory.StartNew()并行执行这些。

任务涉及COM交互。当我执行任务(本应该并行执行)时,main / gui线程显示忙碌光标并且没有响应。

进行COM调用的对象是在使用单线程单元的主线程中创建的。 在这些帖子中:

我读到这可能是原因。

所以我的问题是:如果这是一个补救措施的原因?

以下是代码的样子(简化):

    // the Main() method is a STA which could be important?
    [STAThread]
    static void Main()
    {
     //...
    }


    // inside the MainForm class
    private AComWrapperCreatedByCSharp comWrapper;

    private void button1Click(object sender, EventArgs e)
    {
        var myCancellationSource = new CancellationTokenSource();

        if (someCondition)
        {

            // both alternatives did not work

            //Task.Factory.StartNew(
            ThreadPool.QueueUserWorkItem(
                _ =>
                {
                    try
                    {
                        CancellationToken cancellationToken = myCancellationSource.Token;

                        // the main thread will respond while this tasks sleeps!
                        Thread.Sleep(5000);

                        cancellationToken.ThrowIfCancellationRequested();

                        // that's where the task's thread is when I pause execution 
                        // while the gui is not responding
                        var result = comWrapper.CallSeveralLongerLastingCOMOperations();

                        cancellationToken.ThrowIfCancellationRequested();

                        this.BeginInvoke(new UpdateDelegate(() =>
                        {
                            handle(result);
                        }));
                    }
                    catch (OperationCanceledException)
                    {
                        return;
                    }
                    catch (Exception ex)
                    {
                        threadSafeLogging(string.Format(@"An exception occurred: ""{0}""", ex));
                        return;
                    }
                }

                // I tried adding these lines when starting the Task.Factory.... solution
                //,"factory started thread",_updateProjectsDevicesAndLibrariesTaskCancellationToken.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default
                );

        }
    }

由于

这是@Hans Passant提到的解决方案:

    // inside the MainForm class
    // the COM access object is no longer created in the main thread
    private AComWrapperCreatedByCSharp comWrapper; // = new AComWrapperCreatedByCSharp;

    private void someInitializationMethodInTheMainThread()
    {
      var th = new Thread(() =>
        {
          comWrapper = CreateComWrapper();
        });
      th.SetApartmentState(ApartmentState.MTA);
      th.Start();
      th.Join();
    }

如果我做对了,这个线程的唯一目的是在主线程的非STA中创建一个对象!

0 个答案:

没有答案