0

I am working on SAP B1 add-on and try to make it possible to select printername from PrintDialog. Because of this error:

Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it.

I made a version of this solution for OpenFileDialog: https://stackoverflow.com/a/49553212

Thread t = new Thread(() =>
{
    using (var printerDialog = new System.Windows.Forms.PrintDialog())
    {
        var dr = printerDialog.ShowDialog(new System.Windows.Forms.Form());
        if (dr == System.Windows.Forms.DialogResult.OK)
        {
            var printer = printerDialog.PrinterSettings.PrinterName;
            var cel = matrix.Columns.Item(colUID).Cells.Item(row).Specific;
            ((EditText)cel).String = printer;
        }
    }
});

// Kick off a new thread
t.IsBackground = true;
t.SetApartmentState(ApartmentState.STA);
t.Start();

But for code works only 1 time. Second time program breaks on the following line, without error.

var dr = printerDialog.ShowDialog(new System.Windows.Forms.Form());

After restarting application is works again 1 time.

Gerrit
  • 1
  • 1
  • Two basic rules for an STA thread: never block and run a dispatcher loop. Not observing those rules causes deadlock. https://stackoverflow.com/a/21684059/17034 – Hans Passant Mar 02 '22 at 16:37

1 Answers1

0

I would not recommend your proposed solution.

I'm not familiar with SAP B1, but in general an application should only have a single UI thread. So the correct solution should be to show the print dialog on the UI thread, if you are on a background thread, see how should I update the UI from a background thread.

If this is not possible for some reason I would suggest creating a single extra UI thread that is kept alive for the duration of the application. I.e. start a thread that creates a hidden window that is never closed, whenever you need to show a printer dialog you can call .Invoke on that window object to do whatever you need to do. But having multiple UI threads can make your program difficult to reason about, and may cause odd UI bugs, so I would only do this as a last resort.

If your application do not have any UI thread at all you should be able to use the same hidden-window trick. But it seem rather odd to show a printer UI from a non-UI application.

JonasH
  • 28,608
  • 2
  • 10
  • 23