TFTPアプリで正しくC#を使用しているのを使っているのかわからない

StackOverflow https://stackoverflow.com//questions/25070454

  •  26-12-2019
  •  | 
  •  

質問

私はこの Pre-Make C#formを使って使用しようとしています。著者のサーバーの例では、それは素晴らしい機能で、コンソールアプリを使います。私が彼のコンソールの例を私のフォームアプリに移植しようとしていないとき(エラーはありません。

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

私が正しく理解しているかどうかわからないが、Console.Read()ブロックはアプリを終了から保持していると思います。この場合、どのようにしてフォームアプリと同等のものを実装しますか。私はちょうどあなたの頭を「使う」の周りに入ることはできません。申し訳ありませんがC#。

役に立ちましたか?

解決

Windowsフォームは、ユーザーが明示的に閉じられるまで常に開いたままになります。それらは常にユーザー入力のメッセージキューを読み取るスレッドがありますので、無制限のコンソールアプリケーションは同じ方法で終了しません。 Windowsフォームでは、コンソールアプリよりもマルチスレッドと並行性についてもう少し心配する必要があります。それはほとんど自然に来るが、常にではありません。

そのため、Console.Read()と同等のものを使用して、ユーザーが要求するまでusing廃棄の実行を保持することはできません。あなたがした場合、あなたのフォームは単に応答者に見えるでしょう。

しかし、あなたは運を楽しんでいます! C#のusingブロックは、オブジェクトを完了した後にIDisposable.Dispose()を呼び出すことを覚えている構文シュガー以外のものではありません。したがって、Formsプロジェクトのこれと同等のものは、serverオブジェクトをクラス全体のフィールドに格納してから、server.Dispose()イベントを呼び出すだけです。それはもちろん、ほんの一例です。それがより適切であると感じた場合は、Button.Clickでも実行できます。

高レベル、あなたはこのようなことをしたいです:

  1. フォームクラスForm.Closingのフィールドを宣言します。
  2. TftpServer server;イベントを登録し、あなたがあなたのConstructorで機能するためにLoadに必要なものは何でも。
  3. serverイベントでserverフィールドを開きます。
  4. Form_Loadの存続期間中に適合しているようにserverのイベントを使用してください。並行性について心配する必要があるかもしれませんが、それが別の質問の問題です。
  5. フォームのFormイベントでserver.Dispose()を呼び出します。
  6. 本質的に、

    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;
            }
        }
    }
    
    .

他のヒント

問題は、サーバーを配置することが閉じているものです。使用を念頭に置いてください。次の2つのコードチャンクは実際には同等です。

var foo = new Foo();
try
{
   foo.Do();
}
finally
{
   foo.Dispose();
}
.


using (var foo = new Foo())
{
   foo.Do();
}
.

メインスレッドをコンソールアプリで終了するのを妨げていますが、フォームアプリでは異なります。問題は、ある種のブロッキング操作を行うことで、スレッド内のスレッドを使用する必要があるというわけではありません。それは悪いでしょう、そして振る舞いはあなたのフォームアプリをロックアップするでしょう。問題は使用したくないです。サーバーを起動してから、後でアプリケーション終了時に、または[停止]をクリックしてから、[Dispose()で明示的に処理]をクリックします。

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])

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top