سؤال

أحاول أن قم بتشغيل tclhttpd في مترجم تابع ولكن تم تعديله قليلاً ليعمل ضمن tclkit.الكود الموجود أدناه "يعمل" (أستطيع أن أضرب http://localhost:8015) ولكن لا يصل مطلقًا إلى سطر الوضع في الأسفل لأن "الخادم لا يعود، بل يدخل [vwait Forever]".ولكن عندما أحاول "خدعة ما بعد 0"، على سبيل المثال.الإضافة المسبقة "بعد 0" إلى السطر "$httpd eval $cmd"، لا يعمل الخادم على الإطلاق، لذلك أفترض "يجب معالجة الأخطاء بواسطة bgerror"

ومع ذلك، لا يمكنني العثور على أمثلة جيدة لكيفية استخدام bgerror، بالإضافة إلى أن بحثي يوضح أن الاتفاقية الآن هي استخدام "interp bgerror".يرجى الاطلاع على أول زوجين من الأمثلة التي تم إرجاعها بواسطة http://www2.tcl.tk/_/gsearch?S=bgerror;يحتوي الرابط الأول على عبارة "املأ الحيل والأمثلة المفيدة لاستخدام bgerror" ولكن بعد ذلك لا توجد نماذج يمكنني تمييز كيفية تطبيقها، ويخلص الرابط الثاني إلى "أنا مهتم بأمثلة حول كيفية استخدام هذا."

package require starkit
starkit::startup

set httpd_args [list]
set httpd [interp create]
$httpd eval "set argc [llength $httpd_args]"
set cmdargv "set argv [list $httpd_args ]"
$httpd eval "set topdir $starkit::topdir"
$httpd eval $cmdargv

set cmd [list source [file join $starkit::topdir bin/httpd.tcl]]
$httpd eval $cmd

puts "if seeing this controlled has returned"
هل كانت مفيدة؟

المحلول

وأنا لا أفهم تماما مسألة تسألون. هذا يبدو وكأنه هدفك هو لبدء ملقم HTTP في مترجم واحد ولكن التفاعل بطريقة أو بأخرى مع المترجم الرئيسي. هل هذا صحيح؟ إذا كان الأمر كذلك، ماذا يجب أن نفعل ذلك مع bgerror؟

هل أنت على علم أنه على الرغم من أنك تقوم بتشغيل الخادم في مترجم مستقل، فمن <م> لا تشغيل في موضوع مستقل؟ وهذا هو، لا يمكن (*) التفاعل مع المترجم الرئيسي في حين يتم حظر إما مترجم من قبل vwait.

و(*) يمكنك، إذا يأخذ تعاملك شكل الحاجيات تاكا التي تأخذ أيضا الاستفادة من حلقة الحدث

وأما عن كيفية استخدام bgerror، وهناك عدة طرق أنه يعمل. آلية الافتراضي باستدعاء الدالة "bgerror" والتي قد تحدد لتفعل ما تريد، وتأخذ سلسلة واحدة (نص رسالة الخطأ) ويفعل شيئا معها، وهذا <م> شيء يمكن أن يكون ل طباعة الخطأ المعياري، وتبين أنه في الحوار، والكتابة إلى ملف، الخ.

وكمثال على ذلك، والنظر في هذه الدورة التفاعلية:

% proc bgerror {s} {puts "hey! I caught an error: $s"}
% # after 30 seconds, throw an error
% after 30000 {error "this is an error"}
after#0
% # after 40 seconds, terminate the event loop
% after 40000 {set ::done 1}
after#1
% # start the event loop
% vwait ::done
hey! I caught an error: this is an error
% # this prompt appears after 40 seconds or so

ويمكنك أيضا التسجيل الخاص معالج خطأ، كما هو موضح في وثائق "bgerror التفسيرى". جاء ذلك جنبا إلى جنب في تى سى ال 8.5، على الرغم من أنه كان علة الذي لم يحدد حتى 8.5.3.

وعلى سبيل المثال:

% set foo [interp create]
interp0
% $foo eval {proc myErrorHandler {args} {puts "myErrorHandler: $args"}}
% $foo bgerror myErrorHandler
myErrorHandler
% # after 30 seconds, throw an error
% $foo eval {after 30000 {error "this is an error"}}
after#0
% # after 40 seconds, terminate the loop
% $foo eval {after 40000 {set ::done 1}}
after#1
% $foo eval {vwait ::done}
myErrorHandler: {this is an error} {-code 1 -level 0 -errorcode NONE -errorinfo {this is an error
    while executing
"error "this is an error""
    ("after" script)} -errorline 1}
% # this prompt appears after 40 seconds or so

هل هذه مساعدة في الإجابة على سؤالك؟

نصائح أخرى

تم تحريره بالكامل بناءً على تعليقات OP...

الحيلة بعد 0 هي السطر التالي:

after 0 $httpd eval $cmd

ما يفعله هذا هو إخبار interp بإضافة الأمر المعني ($http eval $cmd) إلى قائمة انتظار الأحداث، مما يعني أنه سيتم تشغيله بمجرد بدء حلقة الحدث (أو العودة إليه إذا كانت قد بدأت بالفعل).يمكنك رؤية الاعتماد على حلقة الحدث في التعليق التالي من تلك الصفحة (بقلم جاكوب ليفي):

يجب أن أشير إلى أن هذا يعتمد على كون حلقة الحدث نشطة.

أعتقد أنك تقوم بتشغيل Tclsh عادي، مما يعني أنك لن تدخل أبدًا في حلقة الحدث (يدخل Wish Shell في حلقة الحدث في نهاية البرنامج النصي، بينما لا تدخل Tcl Shell).الطريقة القياسية للدخول إلى حلقة الحدث هي تشغيل الأمر التالي بمجرد وصولك إلى نهاية كود Tcl الخاص بك:

# Enter the event loop and stay in it until someone 
# sets the "forever" variable to something
vwait forever

ومع ذلك، فإن أي شيء لديك بعد vwait لن يعمل إلا بعد الخروج من حلقة الحدث.إذا كنت تريد تشغيل httpd بالتوازي مع التعليمات البرمجية الخاصة بك، فستحتاج إلى إما:

  • استخدم عدة مواضيع، أو اكتب...وهو في الحقيقة ليس بهذه الصعوبة
  • الكود يعتمد على الحدث ...الأمر الذي يتطلب منك فهم البرمجة القائمة بشكل جيد بما يكفي لمنع حرمان أجزاء من التعليمات البرمجية من وقت التنفيذ.

امل ان يساعد.

إذا كنت فهمت بشكل صحيح ما تريد القيام به، يجب أن التعليمات البرمجية مشابها لما يلي:

set httpd_id [thread::create -preserved]
thread::send $http_id "source [file join $starkit::topdir bin/httpd.tcl]"

في هذه الطريقة سيكون لديك TclHttpd تعمل في موضوع، دون الحاجة إلى القلق لمشكلة vwait

إذا كنت تريد أيضا الحصول على معلومات عن أي خطأ أثناء تنفيذ هتبد، TclHttp يرسل كافة الأخطاء إلى ملف السجل. يمكنك تكوين مسار دخول بهذا الأمر:

Log_SetFile "/logs/httpd_log"

وتحتاج إلى أن يكون في هتبد :: تسجيل الحزمة.

وآمل أن يساعد هذا.

scroll top