[Mono-list] Mono, Windows Forms, and Headless operation

George, Glover E ERDC-RDE-ITL-MS Glover.E.George at erdc.dren.mil
Fri Jan 8 23:25:59 UTC 2016


Thanks Jordan.

It turns out, I may have been conflating two problems into one.  The fact
that I needed to show the windows form was because I needed a message loop
to process the BackgroundWorker¹s events.  Turns out I can just call
Application.Run() with no parameter, and it will cause the UI thread to
start a message loop that works fine.

The real problem is that it still seems as though mono requires X11 for
Windows Forms apps.  So I created a new project from scratch to test this
theory.  It is a very simple app.  It¹s a simple form with a button
(runButton) and a progress bar (progressBar1) (Designer code is left out
due to space).

PROGRAM.CS
static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
  [STAThread]
  static void Main()
  {
    // Instantiate the Main Form
    Form frm = new Form1();
    Application.Run();
  }
    }


#FORM1.cs
public partial class Form1 : Form
    {
  public Form1()
  {
    InitializeComponent();
    runButton_Click(this,null);
  }

  private void runButton_Click(object sender, EventArgs e)
  {
    BackgroundWorker worker = new BackgroundWorker();
    worker.WorkerReportsProgress = true;
    worker.DoWork += DoWork;
    worker.ProgressChanged += ProgressChanged;
    worker.RunWorkerCompleted += WorkerCompleted;
    worker.RunWorkerAsync(worker);
  }

  public void DoWork(object sender, EventArgs e)
  {
    var worker = sender as BackgroundWorker;
    for (int i = 0; i < 100; i++)
    {
      Thread.Sleep(100);
      worker.ReportProgress(i);
    }
  }

  public void ProgressChanged(object sender, ProgressChangedEventArgs e)
  {
    progressBar1.Value = e.ProgressPercentage;
  }

  public void WorkerCompleted(object sender, EventArgs e)
  {
    MessageBox.Show("I'm done!!!");
    Application.Exit();
  }
}


This program runs perfectly well without displaying anything so long as
DISPLAY is set to a valid X11 Display (:0).  However, if I unset DISPLAY
(export DISPLAY=), then I get the following error.  Note, this is similar
to the error I previously posted, but the stack trace and error message is
a bit more detailed (don¹t know why yet):


Unhandled Exception:
System.TypeInitializationException: The type initializer for
'System.Windows.Forms.WindowsFormsSynchronizationContext' threw an
exception. ---> System.TypeInitializationException: The type initializer
for 'System.Windows.Forms.XplatUI' threw an exception. --->
System.ArgumentNullException: Could not open display (X-Server required.
Check your DISPLAY environment variable)
Parameter name: Display
  at System.Windows.Forms.XplatUIX11.SetDisplay (IntPtr display_handle)
<0x4100b560 + 0x00b9b> in <filename unknown>:0
  at System.Windows.Forms.XplatUIX11..ctor () <0x41009890 + 0x001df> in
<filename unknown>:0
  at System.Windows.Forms.XplatUIX11.GetInstance () <0x410096c0 + 0x0005b>
in <filename unknown>:0
  at System.Windows.Forms.XplatUI..cctor () <0x41009390 + 0x00137> in
<filename unknown>:0
  --- End of inner exception stack trace ---
  at System.Windows.Forms.Theme.get_MenuAccessKeysUnderlined ()
<0x41009340 + 0x0000b> in <filename unknown>:0
  at System.Windows.Forms.SystemInformation.get_MenuAccessKeysUnderlined
() <0x41004790 + 0x00017> in <filename unknown>:0
  at System.Windows.Forms.Control..ctor () <0x410033b0 + 0x00243> in
<filename unknown>:0
  at (wrapper remoting-invoke-with-check)
System.Windows.Forms.Control:.ctor ()
  at System.Windows.Forms.WindowsFormsSynchronizationContext..cctor ()
<0x410046c0 + 0x0001f> in <filename unknown>:0
  --- End of inner exception stack trace ---
  at System.Windows.Forms.Control..ctor () <0x410033b0 + 0x00053> in
<filename unknown>:0
  at System.Windows.Forms.ScrollableControl..ctor () <0x41002e40 +
0x0000f> in <filename unknown>:0
  at System.Windows.Forms.ContainerControl..ctor () <0x41002cb0 + 0x00027>
in <filename unknown>:0
  at System.Windows.Forms.Form..ctor () <0x41002430 + 0x000bb> in
<filename unknown>:0
  at test2.Form1..ctor () <0x40ffff90 + 0x0001f> in <filename unknown>:0
  at (wrapper remoting-invoke-with-check) test2.Form1:.ctor ()
  at test2.Program.Main () <0x40fffd90 + 0x0001b> in <filename unknown>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.TypeInitializationException: The
type initializer for
'System.Windows.Forms.WindowsFormsSynchronizationContext' threw an
exception. ---> System.TypeInitializationException: The type initializer
for 'System.Windows.Forms.XplatUI' threw an exception. --->
System.ArgumentNullException: Could not open display (X-Server required.
Check your DISPLAY environment variable)
Parameter name: Display
  at System.Windows.Forms.XplatUIX11.SetDisplay (IntPtr display_handle)
<0x4100b560 + 0x00b9b> in <filename unknown>:0
  at System.Windows.Forms.XplatUIX11..ctor () <0x41009890 + 0x001df> in
<filename unknown>:0
  at System.Windows.Forms.XplatUIX11.GetInstance () <0x410096c0 + 0x0005b>
in <filename unknown>:0
  at System.Windows.Forms.XplatUI..cctor () <0x41009390 + 0x00137> in
<filename unknown>:0
  --- End of inner exception stack trace ---
  at System.Windows.Forms.Theme.get_MenuAccessKeysUnderlined ()
<0x41009340 + 0x0000b> in <filename unknown>:0
  at System.Windows.Forms.SystemInformation.get_MenuAccessKeysUnderlined
() <0x41004790 + 0x00017> in <filename unknown>:0
  at System.Windows.Forms.Control..ctor () <0x410033b0 + 0x00243> in
<filename unknown>:0
  at (wrapper remoting-invoke-with-check)
System.Windows.Forms.Control:.ctor ()
  at System.Windows.Forms.WindowsFormsSynchronizationContext..cctor ()
<0x410046c0 + 0x0001f> in <filename unknown>:0
  --- End of inner exception stack trace ---
  at System.Windows.Forms.Control..ctor () <0x410033b0 + 0x00053> in
<filename unknown>:0
  at System.Windows.Forms.ScrollableControl..ctor () <0x41002e40 +
0x0000f> in <filename unknown>:0
  at System.Windows.Forms.ContainerControl..ctor () <0x41002cb0 + 0x00027>
in <filename unknown>:0
  at System.Windows.Forms.Form..ctor () <0x41002430 + 0x000bb> in
<filename unknown>:0
  at test2.Form1..ctor () <0x40ffff90 + 0x0001f> in <filename unknown>:0
  at (wrapper remoting-invoke-with-check) test2.Form1:.ctor ()
  at test2.Program.Main () <0x40fffd90 + 0x0001b> in <filename unknown>:0



>From the looks of that error message, is X truly a requirement for any app
that is calling Windows Forms controls?  Also note, the project type for
this project is Console App.  It appears that by dynamically loading (or
is it the link?) anything from System.Windows.Forms causes mono to require
X. 
‹ ‹ ‹ 

Glover E. George
Computer Scientist
Information Technology Laboratory
US Army Engineer Research and Development Center
Vicksburg, MS 39180
601-634-4730





On 1/8/16, 10:29 AM, "mono-list-bounces at lists.ximian.com on behalf of
Robert Jordan" <mono-list-bounces at lists.ximian.com on behalf of
robertj at gmx.net> wrote:

>On 07.01.2016 22:24, George, Glover E ERDC-RDE-ITL-MS wrote:
>> Hi all,
>>
>> We¹re currently porting a Windows Forms Application to Mono, and have
>> generally had great success.  However, we have now hit a critical
>> decision point, and were hoping for some guidance on the best route
>> forward.   If we don¹t have X11, mono fails to run Windows Forms code
>> with the following error:
>>
>> From: System.Windows.Forms, at: Void .ctor(), Error Message: The type
>> initializer for
>> 'System.Windows.Forms.WindowsFormsSynchronizationContext' threw an
>> exception.
>>
>> Question First: The main question I had for the Mono list is this.
>> Is it possible to have mono run Windows Forms code without trying to
>> open X11 (I.e. headless mode)?  What triggers mono to request an X11
>> display? Is it the project type?  Is it the call to an object that
>> inherits from a Windows Forms control?  I don¹t need to see the form,
>> but if I¹m using BackgroundWorkers, I need the form's event handler,
>> don¹t I?
>
>
>BackgroundWorker does not depend upon System.Windows.Forms, i.e.
>it can use it headless.
>
>The exception you're experiencing is caused by the synchronization
>context set and used by WinForms.
>
>Supposing that you don't need any kind of synchronization, you
>may want to replace the synchronization context with a simple
>one.
>
>I don't know if the most simple one
>(System.Threading.SynchronizationContext)
>would be enough or if you have to subclass it. Have a look
>at its sources and at
>System.Windows.Forms.WindowsFormsSynchronizationContext.
>
>Robert
>
>_______________________________________________
>Mono-list maillist  -  Mono-list at lists.ximian.com
>Blockedhttp://lists.ximian.com/mailman/listinfo/mono-listBlocked
>



More information about the Mono-list mailing list