لست متأكدًا مما إذا كنت أستخدم "استخدام" c# بشكل صحيح في تطبيق tftp
سؤال
أحاول استخدامها هذا تطبيق خادم 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
إذا كان ذلك يبدو أكثر ملاءمة.
رفيع المستوى، تريد أن تفعل شيئًا مثل هذا:
- قم بتعريف حقل في فئة النموذج الخاص بك
TftpServer server;
. - سجل أ
Load
الحدث وكل ما تحتاجه لجهودكمserver
لتعمل في المنشئ الخاص بك. - افتح
server
الميدان فيForm_Load
حدث. - استخدم ال
server
الأحداث التي تراها مناسبة خلال حياتكForm
.ربما يتعين عليك أو لا داعي للقلق بشأن التزامن، ولكن هذا أمر يتعلق بسؤال آخر. - يتصل
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
}
هناك خيار آخر نسيت أن أذكره وهو تجاوز التخلص في النموذج الخاص بك.ربما تريد أن تفعل هذا.باستخدام هذا الخيار، نضمن لك التخلص من الخادم الخاص بك (باستثناء بعض الأحداث التي من شأنها أن تمنع التخلص منه في أي من الاتجاهين [على سبيل المثال.نفدت الذاكرة ])