STA، MTA وكابوس OLE
-
21-08-2019 - |
سؤال
ولقد لتشمل تطبيق. NET في التطبيق. NET آخر والبرنامج المساعد. واجهة البرنامج المساعد يتطلب مني أن ترث من شكل القالب. ثم يتم إرفاق نموذج في MDI عندما يتم تحميل البرنامج المساعد.
وكل شيء يعمل حتى الآن ولكن كلما أسجل لسحب وإسقاط الأحداث، تعيين وضع الإكمال التلقائي لمنسدل أو في مختلف حالات أخرى أحصل على استثناء التالية:
<اقتباس فقرة>... يجب تعيين موضوع الحالي ل وضع الشقة موضوع واحد (STA) قبل المكالمات OLE يمكن تقديمها. التأكد من أن الوظيفة الرئيسية لديه تميز STAThreadAttribute على ذلك ...
اقتباس فقرة>ويتم تشغيل التطبيق الرئيسي في MTA وتطويره من قبل شركة أخرى، حتى لا يكون هناك شيء يمكنني القيام به حيال ذلك.
وحاولت أن تفعل الأشياء التي تسبب هذه الاستثناءات في المواضيع STA، إلا أن ذلك لم يحل المشكلة أيضا.
وقد أي شخص كان في نفس الوضع؟ هل هناك أي شيء يمكنني القيام به لحل هذه المشكلة؟
المحلول 3
تحديث: أصدرت الشركة نسخة STA جديد. السؤال لم يعد مناسبا.
نصائح أخرى
هل يمكن أن محاولة تفرخ موضوع جديد، وندعو CoInitialize مع 0 على ذلك (الخيوط أبارمينت) وتشغيل التطبيق الخاص بك في هذا الموضوع. ومع ذلك فلن تكون لتحديث التحكم مباشرة في هذا الموضوع يجب عليك استخدام Control.Invoke عن كل تعديل واجهة المستخدم.
وأنا لا أعرف إذا كان هذا هو الذهاب إلى العمل على وجه اليقين، ولكن هل يمكن أن تحاول ذلك.
وجريت مؤخرا إلى هذه المشكلة نفسي أثناء محاولة قراءة الصور من كاميرا الويب. ما انتهى به تم خلق طريقة التي ولدت في موضوع STA الجديد، الذي تم تشغيل طريقة ترابط واحد.
المشكلة
private void TimerTick(object sender, EventArgs e)
{
// pause timer
this.timer.Stop();
try
{
// get next frame
UnsafeNativeMethods.SendMessage(this.captureHandle, WindowsMessageCameraGetFrame, 0, 0);
// copy frame to clipboard
UnsafeNativeMethods.SendMessage(this.captureHandle, WindowsMessageCameraCopy, 0, 0);
// notify event subscribers
if (this.ImageChanged != null)
{
IDataObject imageData = Clipboard.GetDataObject();
Image image = (Bitmap)imageData.GetData(System.Windows.Forms.DataFormats.Bitmap);
this.ImageChanged(this, new WebCamEventArgs(image.GetThumbnailImage(this.width, this.height, null, System.IntPtr.Zero)));
}
}
catch (Exception ex)
{
MessageBox.Show("Error capturing the video\r\n\n" + ex.Message);
this.Stop();
}
}
// restart timer
Application.DoEvents();
if (!this.isStopped)
{
this.timer.Start();
}
}
والحل: حرك منطق موضوع واحد لطرقها الخاصة، واستدعاء هذا الأسلوب من موضوع STA جديد
private void TimerTick(object sender, EventArgs e)
{
// pause timer
this.timer.Stop();
// start a new thread because GetVideoCapture needs to be run in single thread mode
Thread newThread = new Thread(new ThreadStart(this.GetVideoCapture));
newThread.SetApartmentState(ApartmentState.STA);
newThread.Start();
// restart timer
Application.DoEvents();
if (!this.isStopped)
{
this.timer.Start();
}
}
/// <summary>
/// Captures the next frame from the video feed.
/// This method needs to be run in single thread mode, because the use of the Clipboard (OLE) requires the STAThread attribute.
/// </summary>
private void GetVideoCapture()
{
try
{
// get next frame
UnsafeNativeMethods.SendMessage(this.captureHandle, WindowsMessageCameraGetFrame, 0, 0);
// copy frame to clipboard
UnsafeNativeMethods.SendMessage(this.captureHandle, WindowsMessageCameraCopy, 0, 0);
// notify subscribers
if (this.ImageChanged!= null)
{
IDataObject imageData = Clipboard.GetDataObject();
Image image = (Bitmap)imageData.GetData(System.Windows.Forms.DataFormats.Bitmap);
// raise the event
this.ImageChanged(this, new WebCamEventArgs(image.GetThumbnailImage(this.width, this.height, null, System.IntPtr.Zero)));
}
}
catch (Exception ex)
{
MessageBox.Show("Error capturing video.\r\n\n" + ex.Message);
this.Stop();
}
}