2012-11-05 38 views
0

我正在使用COM和Acrobat SDK打印PDF的应用程序。该应用程序是用C#,WPF编写的,我试图弄清楚如何在单独的线程上正确运行打印。我已经看到BackgroundWorker使用线程池,因此不能设置为STA。我知道如何创建一个STA线程,但我不确定我会怎样从STA线程报告进度:从COM/STA线程向WPF UI线程报告进度

Thread thread = new Thread(PrintMethod); 
thread.SetApartmentState(ApartmentState.STA); //Set the thread to STA 
thread.Start(); 
thread.Join(); //Wait for the thread to end 

如何在这样创造了一个STA线程报告进度我的WPF的ViewModel?

回答

2

其实不是,你需要从但报告进度不的(现有)STA线程,其中UI运行。

你可以做到这一点无论是通过BackgroundWorker功能(ReportProgress是开始BackgroundWorker线程上传递 - 这应该是你的UI线程),或者使用UI线程的Dispatcher(通常Dispatcher.BeginInvoke)。


编辑:
对于你的情况,与BackgroundWorker的解决方案是行不通的,因为它的线程不是STA。所以,你需要只是平时DispatcherlInvoke工作:

// in UI thread: 
Thread thread = new Thread(PrintMethod); 
thread.SetApartmentState(ApartmentState.STA); //Set the thread to STA 
thread.Start(); 

void PrintMethod() // runs in print thread 
{ 
    // do something 
    ReportProgress(0.5); 
    // do something more 
    ReportProgress(1.0); 
} 

void ReportProgress(double p) // runs in print thread 
{ 
    var d = this.Dispatcher; 
    d.BeginInvoke((Action)(() => 
      { 
       SetProgressValue(p); 
      })); 
} 

void SetProgressValue(double p) // runs in UI thread 
{ 
    label.Content = string.Format("{0}% ready", p * 100.0); 
} 

如果您当前的对象没有一个Dispatcher,你可以把它从你的UI对象或视图模型(如果使用一个)。

+0

但是COM组件也需要在STA线程中运行,并且我不希望它在UI线程中运行,因为它需要很长时间。 – jle

+0

@jle:是的,COM可以在自己的STA线程中运行。无论如何,UI线程也是一个STA。如果你不能使用'BackgroundWorker'(因为它的工作线程不是STA),你可以用'Dispatcher.BeginInvoke'来报告进度。 – Vlad

+0

所以有这样的:http://dotnetventures.wordpress.com/2011/07/30/maintaining-a-wpf-applications-ui-responsive-while-calling-com-objects/,它显示了如何去做,但我不明白为什么我会这样做,当我可以创建一个调度程序线程? – jle