How to access a COM object in BackgroundWorker?

I have a WPF application and in the main form the user is allowed to select several files (Excel), and then click the button to extract the data and load it into the database. Everything works great.

Now I wanted to implement an employment indicator.

So, I did this, declare the BackgroundWorker stream and load the database (which takes time) as a background stream. The busy indicator is set respectively at the start and end of the stream. The problem is inside my boot process, I am accessing a buffer to print some messages. Therefore, I came across the following error, which is obvious.

"Current thread must be set to single thread apartment (STA) mode before OLE calls can be made."

BackgroundWorker has an MTA by default. So what is the best way to overcome this problem?

the code:

Public WithEvents BgWorker As BackgroundWorker = New BackgroundWorker()

 Private Sub MainWindow_Loaded() Handles Me.Loaded
    AddHandler BgWorker.DoWork, AddressOf ExtractData
    AddHandler BgWorker.RunWorkerCompleted, AddressOf BgWorker_RunWorkerCompleted        
End Sub

Private Sub btnExtract_Click(sender As Object, e As RoutedEventArgs)

    .....

    Try
        .....

       Me.busyIndicator.IsBusy = True
       BgWorker.RunWorkerAsync(Me.cmbFormats.SelectedItem.ToString.Trim())

    Catch ex As Exception
        Utility.Message.ErrorMessage(ex)
    End Try

End Sub

completed event:

Private Sub BgWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
    busyIndicator.IsBusy = False
End Sub

DoWork:

Private Sub ExtractData(sender As Object, e As DoWorkEventArgs)
    Dim exformat As IExtractor = New FormatFactory().CreateInstance(e.Argument.ToString())
    If (exformat.FeedToDb(filename)) Then
        Utility.Message.SuccessMessage("Successfully Extracted to database")
    Else
    End If
 End Sub

Utility.Message.SuccessMessage:

 Public Shared Sub SuccessMessage(msg As String)
    Dim M As New Text.StringBuilder
    M.AppendLine()
    M.AppendLine(msg)
    M.AppendLine()
    Clipboard.Clear() 'problem with MTA
    Clipboard.SetText(M.ToString)
    MsgBox(M.ToString, MsgBoxStyle.Information, "FF IT")
End Sub
+4
4

, , FeedToDb

, . :

  • BackgroundWorker - , . , () - . , , , Facebook Solitaire. "" , . , .

  • MsgBox() . , , . MsgBox - , , . , , . , . MsgBox , . Windows , BackgroundWorker . . , , , . , , . . . , , . , , , , , .

  • Clipboard.SetText() , , . , ( ) . , , , , . , Ctrl + V. , , . ListBox - . RichTextBox, , .

, , , , Quick Fix. SuccessMessage(), , :

Public Shared Sub SuccessMessage(msg As String)
    If System.Threading.Thread.CurrentThread.GetApartmentState <> Threading.ApartmentState.STA Then Return
    '' etc...
End Sub
+4

BackgroundWorker ReportProgress , , , .

BackgroundWorker SuccessMessage ReportProgress . , / BackgroundWorker, .

, , , , .

+2

Try using the STAThread attribute at the application entry point. See Link.

+1
source

Create, apply the attribute and start the stream.

System.Threading.Thread thread = new System.Threading.Thread(()=>{/*My Work*/});

Apply the MTA attribute.

thread.TrySetApartmentState(System.Threading.ApartmentState.MTA);

Call start

thread.Start();

+1
source

Source: https://habr.com/ru/post/1539682/


All Articles