简体   繁体   中英

c# simple web server that launches a form on receiving a request

I have a C# application that acts as a web server to the local machine only. I have used the example from this site as the base for my web server.

So, here is my problem, the main application spawns a listener thread to listen for and handle the response.

In Program.cs

static class Program
{
    [STAThread]
    static void Main()
    {
        Application.Run(new SysTrayApp());
    }
}

In SysTrayApp.cs:

public partial class SysTrayApp : Form
{
    ...
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        WebServer myWebServer = new WebServer(WebServer.Response, "http://localhost:8080/");
        myWebServer.Run();
    }
}

In WebServer.cs

...
public void Run()
{
    ThreadPool.QueueUserWorkItem((o) =>
    {
        Console.WriteLine("Webserver running...");
        try
        {
            while (_listener.IsListening)
            {
                var ctx = _listener.GetContext();
                try
                {
                    string rstr = _responderMethod(ctx.Request);
                    byte[] buf = Encoding.UTF8.GetBytes(rstr);
                    ctx.Response.ContentLength64 = buf.Length;
                    ctx.Response.OutputStream.Write(buf, 0, buf.Length);
                }
                catch { } // suppress any exceptions
                finally
                {
                    // always close the stream
                    ctx.Response.OutputStream.Close();
                }
            }
        }
        catch { } // suppress any exceptions
    });
}

When a request is received, I want to display a Windows Form to the local environment (not the HTTP response). The problem is that I am no longer in the main STAThread when I receive the request, so I can't open a form properly.

If I try open it in the listener thread, the form just freezes because the listener starts listening and blocks the thread. A similar thing happens if I open a threadpool thread.

public static string Response(HttpListenerRequest request)
{

    Form form = new Form();
    form.Show();

    return "TEST!";
}

If I open it in a new normal Thread, the form pops up and then the thread closes and then the form closes again.

public static string Response(HttpListenerRequest request)
{
    Thread thread = new Thread(startForm);
    thread.Start();
    return "TEST!";
}

public static void startForm()
{
    Form form = new Form();
    form.Show();
}

So, from what I can figure out, only forms in the main application/UI thread seem to work properly and also, you can't block the main thread, or else the forms freeze. So, from within the WebServer listener, how do I trigger the opening of a form on the main thread? Should I create an event on the main form that launches the second form and try to trigger it from the listener thread?

Or is there a better way to do it?

PS I am a PHP/Python programmer that has had to venture into C# just for a single project, so I am not really sure what I am doing.

You can invoke a method of SysTrayApp in the worker thread as below

public class SysTrayApp : Form
{
    public SysTrayApp()
    {
        Task.Factory.StartNew(Process, TaskCreationOptions.LongRunning);
    }

    void ActualWork(DateTime dt)
    {
        this.Text = dt.ToString();
    }

    void Process()
    {
        while(true)
        {
            this.Invoke((Action)(() => ActualWork(DateTime.Now)));
            Thread.Sleep(1000);
        }
    }
}

BTW: Don't use threads from threadpool for long running tasks. Why .net Threadpool is used only for short time span tasks?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM