لست متأكدًا مما إذا كنت أستخدم "استخدام" c# بشكل صحيح في تطبيق tftp

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

  •  26-12-2019
  •  | 
  •  

سؤال

أحاول استخدامها هذا تطبيق خادم C# tftp المُعد مسبقًا باستخدام نموذج Windows C# الخاص بي.في مثال خادم المؤلفين، الذي يعمل بشكل رائع، يستخدم تطبيق وحدة التحكم.عندما أحاول نقل مثال وحدة التحكم الخاصة به إلى تطبيق النموذج الخاص بي، فإنه لا يعمل (لا توجد أخطاء، فقط لا يتصل) وأعتقد أن مشكلتي تكمن في عبارة "الاستخدام":

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 Forms، يتعين علينا أن نقلق قليلاً بشأن تعدد العمليات والتزامن أكثر مما نفعل في تطبيقات وحدة التحكم.ويأتي في الغالب بشكل طبيعي، ولكن ليس دائما.

ولهذا السبب، لا يمكنك حقًا استخدام ما يعادله Console.Read() لتأجيل تنفيذ الأمر using التخلص منها حتى يطلب المستخدم ذلك.إذا قمت بذلك، فسيظهر النموذج الخاص بك ببساطة غير مستجيب.

ومع ذلك، أنت محظوظ!أ using الكتلة في C# ليست أكثر من مجرد سكر نحوي لتذكر الاتصال IDisposable.Dispose() بعد الانتهاء من استخدام كائن ما.لذا فإن ما يعادل ذلك في مشروع النماذج يمكن أن يكون مجرد تخزين ملف server كائن في حقل على مستوى الفصل الدراسي، ثم الاتصال server.Dispose() على سبيل المثال، أ Button.Click حدث.وهذا بالطبع مجرد مثال.يمكنك أيضًا القيام بذلك Form.Closing إذا كان ذلك يبدو أكثر ملاءمة.

رفيع المستوى، تريد أن تفعل شيئًا مثل هذا:

  1. قم بتعريف حقل في فئة النموذج الخاص بك TftpServer server;.
  2. سجل أ Load الحدث وكل ما تحتاجه لجهودكم server لتعمل في المنشئ الخاص بك.
  3. افتح server الميدان في Form_Load حدث.
  4. استخدم ال serverالأحداث التي تراها مناسبة خلال حياتك Form.ربما يتعين عليك أو لا داعي للقلق بشأن التزامن، ولكن هذا أمر يتعلق بسؤال آخر.
  5. يتصل server.Dispose() في النموذج Dispose حدث.

المضمون،

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

نصائح أخرى

المشكلة هي أن التخلص من الخادم هو ما يغلقه.ضع في اعتبارك أن الاستخدام هو مجرد سكر نحوي.قطعتا التعليمات البرمجية التاليتان متكافئتان [عمليًا]:

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

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

من الجيد أن تمنع سلسلة الرسائل الرئيسية من الخروج في تطبيق وحدة التحكم، ولكن الأمر مختلف في تطبيق النماذج.لا تكمن المشكلة في أنك تحتاج إلى الاحتفاظ بالخيط داخل الاستخدام عن طريق القيام بنوع من عمليات الحظر.قد يكون ذلك أمرًا سيئًا، وسيؤدي هذا السلوك إلى قفل تطبيق النماذج الخاص بك.المشكلة هي أنك لا تريد استخدام استخدام.تريد تجديده عند بدء تشغيل الخادم، وبعد ذلك، عند الخروج من التطبيق، أو عند النقر فوق إيقاف، قم بالتخلص منه بشكل صريح باستخدام Dispose().

في تطبيق وحدة التحكم الخاصة بك TftpServer المثال يستمع حتى يخرج مؤشر الترابط فقط بعد الضغط على المفتاح الذي يتم اكتشافه بواسطة Console.Read()

في تطبيق النماذج الخاص بك ذلك Console.Read() لا ينتظر وهكذا using انتهاء الحظر مما يؤدي إلى خروج مثيل الخادم الخاص بك عن النطاق.

لذلك أنت لا تسيء استخدام using بل الاستخدام المقصود لا يساعدك على الإطلاق.ألق نظرة على استخدام مكتبة المهام الموازية للسماح بتشغيل بعض مهام الخلفية بشكل غير متزامن.

ملاحظة صغيرة تتضاعف أيضًا كإجابة، أنت استطاع استخدم كتلة الاستخدام هنا، ما عليك سوى وضعها في وظيفتك الرئيسية:

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

هناك خيار آخر نسيت أن أذكره وهو تجاوز التخلص في النموذج الخاص بك.ربما تريد أن تفعل هذا.باستخدام هذا الخيار، نضمن لك التخلص من الخادم الخاص بك (باستثناء بعض الأحداث التي من شأنها أن تمنع التخلص منه في أي من الاتجاهين [على سبيل المثال.نفدت الذاكرة ])

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top