以下是我正在尝试使用我的应用程序完成的任务 - 当HTML文件添加到目录时(使用FileSystemWatcher),我想立即使用WebBrowser打印它。除非我遇到以下错误:
System.Threading.ThreadStateException: ActiveX control GUID cannot be instantiated because the current thread is not in a single-threaded apartment
以下是我正在使用的代码遇到此问题。 (我在Main()之前有[STAThread])
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// Create a FileSystemWatcher to monitor all files on drive C.
FileSystemWatcher fsw = new FileSystemWatcher("C:\\Test");
// Watch for changes in LastAccess and LastWrite times, and
// the renaming of files or directories.
fsw.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
// Register a handler that gets called when a
// file is created, changed, or deleted.
//fsw.Changed += new FileSystemEventHandler(OnChanged);
fsw.Created += new FileSystemEventHandler(OnChanged);
//fsw.Deleted += new FileSystemEventHandler(OnChanged);
fsw.EnableRaisingEvents = true;
PrinterSettings settings = new PrinterSettings();
label2.Text = settings.PrinterName;
Thread.CurrentThread.SetApartmentState(ApartmentState.STA);
}
private void OnChanged(object source, FileSystemEventArgs e)
{
notifyIcon1.BalloonTipText = "Printing document " + e.Name + "...";
notifyIcon1.BalloonTipTitle = "Printing Application";
notifyIcon1.BalloonTipIcon = ToolTipIcon.Info;
notifyIcon1.ShowBalloonTip(500);
PrintCOAPage(e.Name);
}
private void PrintCOAPage(string name)
{
try
{
// Create a WebBrowser instance.
WebBrowser webBrowserForPrinting = new WebBrowser();
// Add an event handler that prints the document after it loads.
webBrowserForPrinting.DocumentCompleted +=
new WebBrowserDocumentCompletedEventHandler(PrintDocument);
// Set the Url property to load the document.
webBrowserForPrinting.Url = new Uri(@"C:\\Test\\" + name);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void PrintDocument(object sender,
WebBrowserDocumentCompletedEventArgs e)
{
try
{
// Print the document now that it is fully loaded.
((WebBrowser)sender).Print();
// Dispose the WebBrowser now that the task is complete.
((WebBrowser)sender).Dispose();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
{
this.Show();
this.Activate();
if (this.WindowState == FormWindowState.Minimized)
{
this.WindowState = FormWindowState.Normal;
}
}
private void Form1_Resize(object sender, EventArgs e)
{
if (FormWindowState.Minimized == WindowState)
{
Hide();
}
}
如果你们对此有任何见解,我将非常感谢你的帮助!也许我不应该使用WebBrowser打印HTML文件?
答案 0 :(得分:1)
FSW引发的事件(如Created)将在工作线程上触发。这非常重要,它确保尽快传递通知,并确保FSW使用的内部缓冲区不会溢出。你应该检查一下btw,不要忘记订阅错误事件。
您在事件处理程序中可以执行的操作是有限的,但是,您始终需要知道您的代码在另一个线程中运行。线程安全始终是一个问题。您在此处遇到的具体错误是由此引起的,WebBrowser不是一个线程安全的类。在少数情况下,您实际上会收到警告,指出您使用的是不支持线程的类,更常见的问题是随机错误行为。
Anyhoo,FSW使解决这个问题非常简单。您可以要求它在UI线程上引发事件。它需要一行代码:
fsw.SynchronizingObject = this;
请注意,如果事件的频率很高,这将使FSW陷入困境,并且必须保持您的UI线程响应。不要跳过该错误事件。通过线程安全队列技术上可以将FSW与浏览器分离,您可以在this answer的单独线程上找到运行WebBrowser所需的代码类型。