c# - وزير - نموذج طلب منحة أرض سكنية




لا يُظهر VS2010 رسالة استثناء غير معالج في تطبيق WinForms على إصدار 64 بت من Windows (4)

أنا باستخدام WPF وركضت في هذه المشكلة نفسها. لقد جربت بالفعل اقتراحات هانس 1-3 ، لكن لم أكن أحبهم لأن الاستوديو لن يتوقف في المكان الذي كان فيه الخطأ (لذا لم أتمكن من رؤية المتغيرات الخاصة بي ومعرفة ما هي المشكلة).

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

ومع ذلك ، كان هذا نفس المشكلة 1-3. يتم التفاف الأخطاء التي تحدث أثناء ctor لـ WPF في استثناء Xaml عام. (استثناء داخلي له خطأ حقيقي ، ولكن مرة أخرى كنت أرغب في استراحة فقط في بقعة الاضطراب الفعلية).

ما انتهى به العمل بالنسبة لي هو إنشاء موضوع ، والنوم 50 مللي ثانية ، وإعادته إلى الموضوع الرئيسي وتفعل ما أحتاج ...

    void Window_Loaded(object sender, RoutedEventArgs e)
    {
        new Thread(() =>
        {
            Thread.Sleep(50);
            CrossThread(() => { OnWindowLoaded(); });
        }).Start();
    }
    void CrossThread(Action a)
    {
        this.Dispatcher.BeginInvoke(a);
    }
    void OnWindowLoaded()
    {
        ...do my thing...

بهذه الطريقة سوف يكسر الاستوديو المكان الذي يحدث فيه استثناء غير ملاحظ.

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

1) إنشاء تطبيق Windows Forms جديد (C # ، .NET Framework 4 ، VS2010)

2) أضف التعليمات البرمجية التالية إلى معالج Form1_Load :

int vara = 5, varb = 0;
int varc = vara / varb;
int vard = 7;

أتوقع أن VS يكسر ويظهر رسالة استثناء غير معالج في السطر الثاني. ومع ذلك ، ما يحدث هو أن الخط الثالث يتم تخطيه دون أي رسالة ويبقى التطبيق قيد التشغيل.

ليس لدي هذه المشكلة مع مشاريعي C # الحالية. لذلك أعتقد أن يتم إنشاء مشاريعي الجديدة مع بعض الإعدادات الافتراضية الغريبة.

هل لدى أي شخص فكرة ما هو الخطأ في مشروعي ؟؟؟

حاولت التحقق من المربعات في Debug-> الاستثناءات. ولكن بعد ذلك ، تتعطل عمليات الإعدام حتى لو كنت أتعامل مع الاستثناء في كتلة try-catch ؛ وهو أيضا ليس ما أريد. إذا كنت أتذكر بشكل صحيح ، كان هناك عمود يسمى "الاستثناءات غير المعالجة" أو شيء من هذا القبيل في مربع الحوار هذا ، والتي من شأنها أن تفعل ما أريد excatly. ولكن في مشروعاتي يوجد عمود واحد فقط ("Thrown").


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

مع مقدمة KB976038 ، يمكنك جعل هذا العمل كما كنت تتوقع مرة أخرى. لم أقم بتثبيت الإصلاح العاجل ، لذا أفترض أنه جاء كجزء من Win7 SP1.

هذا ما ورد في هذا المنصب:

إليك بعض التعليمات البرمجية التي من شأنها تمكين الإصلاح العاجل:

public static class Kernel32
{
    public const uint PROCESS_CALLBACK_FILTER_ENABLED = 0x1;

    [DllImport("Kernel32.dll")]
    public static extern bool SetProcessUserModeExceptionPolicy(UInt32 dwFlags);

    [DllImport("Kernel32.dll")]
    public static extern bool GetProcessUserModeExceptionPolicy(out UInt32 lpFlags);


    public static void DisableUMCallbackFilter() {
        uint flags;
        GetProcessUserModeExceptionPolicy(out flags);

        flags &= ~PROCESS_CALLBACK_FILTER_ENABLED;
        SetProcessUserModeExceptionPolicy(flags);
    }
}

يطلق عليه في بداية الطلب الخاص بك:

    [STAThread]
    static void Main()
    {
        Kernel32.DisableUMCallbackFilter();

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

لقد أكدت (مع المثال البسيط المبين أدناه) أن هذا الأمر يعمل كما توقعت.

protected override void OnLoad(EventArgs e) {
    throw new Exception("BOOM");   // This will now get caught.
}

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


هذه مشكلة سيئة ناجمة عن طبقة مضاهاة wow64 التي تسمح بتشغيل التعليمات البرمجية 32 بت على إصدار 64 بت من Windows 7. يبتلع استثناءات في التعليمة البرمجية التي يتم تشغيلها استجابة لإعلام أنشأه مدير النوافذ 64 بت ، مثل حدث Load . منع مصحح الأخطاء من رؤيتها والتدخل فيها. من الصعب إصلاح هذه المشكلة ، تشير مجموعات Windows و DevDiv في Microsoft إلى الأمام والخلف. لا يستطيع DevDiv فعل أي شيء حيال ذلك ، حيث يعتقد Windows أنه السلوك الصحيح والموثق ، وهو أمر غامض.

إنه documented بالتأكيد ولكن لا أحد يفهم العواقب أو يعتقد أنه سلوك معقول. لا سيما عندما يتم إخفاء الإجراء نافذة من عرض بالطبع ، كما هو الحال في أي مشروع يستخدم الطبقات المجمع لإخفاء أنابيب المياه. مثل أي Winforms ، WPF أو MFC التطبيق. المشكلة الأساسية هي أن مايكروسوفت لم تتمكن من اكتشاف كيفية تدفق الاستثناءات من كود 32-بت إلى كود 64-بت الذي تسبب في إعادة الإعلام إلى كود 32-بت الذي يحاول معالجة الاستثناء أو تصحيحه.

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

المشروع> خصائص> علامة التبويب إنشاء> الهدف Platform = AnyCPU وإلغاء تحديد Prefer 32-بت. سيتم تشغيل تطبيقك الآن كعملية 64 بت ، مما يلغي وضع الفشل في wow64. بعض النتائج ، فإنه يعطل "تحرير + متابعة" إصدارات VS قبل VS2013 وقد لا يكون ممكناً دائماً عندما يكون لديك تبعية على رمز 32 بت.

الحلول المحتملة الأخرى:

  • Debug> Exceptions> حدد المربع Thrown لاستثناءات CLR لإجبار مصحح الأخطاء على التوقف عند سطر التعليمة البرمجية التي تطرح الاستثناء.
  • اكتب محاولة / catch في معالج حدث Load و failfast في كتلة catch.
  • استخدم Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException) في الأسلوب Main() بحيث لا يتم تعطيل اعتراض الاستثناء في حلقة الرسالة في وضع التصحيح. ومع ذلك ، فإن هذا يجعل جميع الاستثناءات غير المعالجة يصعب تصحيحها ، حيث يكون حدث ThreadException عديم الفائدة إلى حد كبير.
  • فكر فيما إذا كان رمزك ينتمي حقًا إلى معالج الأحداث Load . من النادر جداً أن تحتاج إليها ، إلا أنها تحظى بشعبية كبيرة في VB.NET وأغنية البجعة لأنها الحدث الافتراضي ، وتضيف نقرًا مزدوجًا معالج الأحداث. أنت في حاجة فعلًا إلى Load أبدًا عندما تكون مهتمًا بحجم الإطار الفعلي بعد تطبيق تفضيلات المستخدم والتطبيق التلقائي. كل شيء آخر ينتمي إلى المنشئ.
  • التحديث إلى ويندوز 8 أو في وقت لاحق ، لديهم هذه المشكلة wow64 حلها.

يمكن أن تكون عملية بسيطة إذا كنت تستطيع نقل شفرة init إلى حدث آخر مثل Form_Shown الذي تم استدعاؤه لاحقًا من Form_Load ، واستخدام علامة لتشغيل رمز بدء التشغيل في النموذج الأول الموضح:

bool firstLoad = true; //flag to detect first form_shown

private void Form1_Load(object sender, EventArgs e)
{
    //firstLoad = true;
    //dowork(); //not execute initialization code here (postpone it to form_shown)
}

private void Form1_Shown(object sender, EventArgs e)
{
    if (firstLoad) //simulate Form-Load
    {
        firstLoad = false;

        dowork();
    }
}

void dowork()
{
    var f = File.OpenRead(@"D:\NoSuchFile756.123"); //this cause an exception!

}






exception-handling