Frage

Ich versuche zu benutzen dieser vorgefertigte C # -TFTP-Server-App mit meinem Windows c # -Formular.Im Beispiel des Autorenservers, das hervorragend funktioniert, verwendet er eine Konsolen-App.Wenn ich versuche, sein Konsolenbeispiel in meine Formular-App zu portieren, funktioniert es nicht (keine Fehler, nur keine Verbindung) und ich glaube, mein Problem liegt in der "using" -Anweisung:

using (var server = new TftpServer())
{
    server.OnReadRequest += new TftpServerEventHandler(server_OnReadRequest);
    server.OnWriteRequest += new TftpServerEventHandler(server_OnWriteRequest);
    server.Start();
    Console.Read();
}

Ich bin mir nicht sicher, ob ich das richtig verstehe, aber ich glaube das Console.Read() blockiert das Beenden der App.Wenn dies der Fall ist, wie würde ich ein Äquivalent mit einer Formular-App implementieren.Ich kann mich einfach nicht mit dem "Benutzen" auseinandersetzen.Entschuldigung, ich bin neu in c #.

War es hilfreich?

Lösung

Windows-Formulare bleiben immer geöffnet, bis sie vom Benutzer explizit geschlossen werden.Sie haben immer einen Thread, der die Nachrichtenwarteschlange für Benutzereingaben liest, sodass sie nicht wie eine uneingeschränkte Konsolenanwendung beendet werden.In Windows Forms müssen wir uns etwas mehr Gedanken über Multithreading und Parallelität machen als in Konsolen-Apps.Es kommt meistens natürlich, aber nicht immer.

Aus diesem Grund können Sie kein Äquivalent zu verwenden Console.Read() um die Ausführung der using entsorgung, bis der Benutzer dies anfordert.Wenn Sie dies täten, würde Ihr Formular einfach nicht reagieren.

Sie haben jedoch Glück!A using block in C # ist nichts anderes als syntaktischer Zucker zum Erinnern an Aufrufe IDisposable.Dispose() nachdem Sie mit einem Objekt fertig sind.Das Äquivalent dazu in einem Formularprojekt könnte also nur das Speichern sein server objekt in einem klassenweiten Feld, dann Aufruf server.Dispose() auf, sagen wir, ein Button.Click Veranstaltung.Das ist natürlich nur ein Beispiel.Sie könnten es auch tun auf Form.Closing wenn sich das angemessener anfühlte.

Auf hoher Ebene möchten Sie so etwas tun:

  1. Deklarieren Sie ein Feld in Ihrer Formularklasse TftpServer server;.
  2. Registrieren Sie ein Load veranstaltung und was auch immer Sie für Ihre server um in Ihrem Konstruktor zu funktionieren.
  3. Öffne deine server feld in der Form_Load Veranstaltung.
  4. Verwenden Sie die server's Ereignisse, wie Sie sehen, so passen während des Lebens Ihres Form.Möglicherweise müssen Sie sich um Parallelität sorgen oder nicht, aber das ist eine Sache für eine andere Frage.
  5. Nennen server.Dispose() in der Form Dispose Veranstaltung.

Im Wesentlichen,

class main : Form
{
    private TftpServer server;

    public main()
    {
        InitializeComponent();

        this.Load += main_Load;

        server = new TftpServer();
        server.OnReadRequest += new TftpServerEventHandler(server_OnReadRequest);
        server.OnWriteRequest += new TftpServerEventHandler(server_OnWriteRequest);
    }

    private void main_Load(object sender, EventArgs e)
    {
        server.Start();
    }

    private void server_OnReadRequest(/* I wasn't sure of the arguments here */)
    {
        // use the read request: give or fetch its data (depending on who defines "read")
    }
    private void server_OnWriteRequest(/* I wasn't sure of the arguments here */)
    {
        // use the write request: give or fetch its data (depending on who defines "write")
    }

    protected override void Dispose(bool disposing)
    {
        if (server != null) // since Dispose can be called multiple times
        {
            server.Dispose();
            server = null;
        }
    }
}

Andere Tipps

Das Problem ist, dass der Server das Gerät ist, was es schließt.Denken Sie daran, dass Sie nur syntaktisch zucker sind.Die folgenden zwei Code-Brocken sind [praktisch] gleichwertig:

generasacodicetagpre.


generasacodicetagpre.

Sie sind fein blockieren, dass der Hauptfaden in einer Konsolen-App endet, aber in einer Formulare-App ist es anders.Das Problem ist nicht, dass Sie den Faden in der Verwendung in der Verwendung halten müssen, indem Sie eine Art Blockiervorgang durchführen.Das wäre schlecht, und das Verhalten würde Ihre Forms-App sperren.Das Problem ist, dass Sie nicht verwenden möchten.Sie möchten, wenn Sie den Server starten, und später, auf Anwendungsausgang oder an einem Stoppklick, explizit mit Dispose () explizit ().

In a console application your TftpServer instance is listening until the thread exits which is only after a key is pressed which is detected by Console.Read()

In your forms app that Console.Read() isn't waiting around and so the using block finishes and that causes your server instance to fall out of scope.

So you are not exactly misusing the using but rather the intended use is not helping you at all. Take a look at using the task parallel library to let some background tasks run asynchronously.

A small note that also doubles as an answer, you could use a using block here, you just put it in your main function:

...(make your form and stuff) 
using (var server = new TftpServer())
{
   server.OnReadRequest += new TftpServerEventHandler(server_OnReadRequest);
   server.OnWriteRequest += new TftpServerEventHandler(server_OnWriteRequest);
   server.Start();
   Application.Run(yourFormHere); //This blocks until the form is closed
}

Another option I forgot to mention is overriding Dispose in your Form. You probably want to do this. With this option you're guaranteed your server will be disposed (bar some event that would prevent it from being disposed either way [ie. being out of memory])

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top