2

それは私が前に見たことのようなものではありません。
(new System.Windows.Forms.Form()).ShowDialog() を呼び出すと、フォームがミリ秒程度表示されてから消えます。
私は呼び出しを追跡し、これを得ました:

System.Windows.Forms.Form.Dispose
System.ComponentModel.Component.Dispose
System.Windows.Forms.Application.ThreadWindows.Dispose
System.Windows.Forms.Application.ThreadContext.DisposeThreadWindows
System.Windows.Forms.Application.ComponentManager.System. Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop
System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner
System.Windows.Forms.Application.ThreadContext.RunMessageLoop
System.Windows.Forms.Form.ShowDialog Esfand.Program.Main C#

これを修正するために頭に浮かぶことは何でも試しました。

このフォームを表示しようとする前に、ログインフォームを表示しましたが。
ログインフォームに特別なことは何もないと思います(通常の退屈なもの、サーバーへの接続、資格情報の送信、データの受信)。
フォームにメインスレッドを使用しています。メッセージングとメッセージ ループの経験があります。ログインフォームでスレッドを使用しました。

編集:コーディ・グレイが提案したことの明確化:

これは私が持っているものですvoid Main(string[]):

LoginForm login = new LoginForm ();
login.ShowDialog ();//works
if (login.DialogResult == DialogResult.OK)
{
    MainForm f = new MainForm ();
    f.ShowDialog ();//won't work
}

新しいスレッドで MainForm を作成して表示すると、すべてが再び機能し始めますが、各フォームでランダムなエラーが発生するため、このソリューションは十分ではありません。

編集 2:
FormClosing イベントはトリガーさえしません。

System.Windows.Forms.Form A;
A = new Form();
A.FormClosing += new FormClosingEventHandler((sender, e) => { System.Diagnostics.Debugger.Break();/*won't work. tried Breakpoints and other stuff too*/ });
A.ShowDialog();

編集 3: HandleDestroyed イベント スタック トレース:

>   Esfand.exe!Esfand.Program.Main.AnonymousMethod__1(object sender = {System.Windows.Forms.Form}, System.EventArgs e = {System.EventArgs}) Line 50 + 0x6 bytes C#
    System.Windows.Forms.dll!System.Windows.Forms.Control.OnHandleDestroyed(System.EventArgs e) + 0x9e bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Form.OnHandleDestroyed(System.EventArgs e) + 0x13 bytes   
    System.Windows.Forms.dll!System.Windows.Forms.Control.WmDestroy(ref System.Windows.Forms.Message m) + 0x54 bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) + 0x547 bytes 
    System.Windows.Forms.dll!System.Windows.Forms.Form.WndProc(ref System.Windows.Forms.Message m) + 0x6d bytes 
    System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg = 2, System.IntPtr wparam, System.IntPtr lparam) + 0x15e bytes    
    [Native to Managed Transition]  
    [Managed to Native Transition]  
    System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DestroyHandle() + 0xf7 bytes 
    System.Windows.Forms.dll!System.Windows.Forms.Control.DestroyHandle() + 0x3e3 bytes 
    System.Windows.Forms.dll!System.Windows.Forms.Control.Dispose(bool disposing) + 0x347 bytes 
    System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.Dispose(bool disposing) + 0x19 bytes 
    System.Windows.Forms.dll!System.Windows.Forms.Form.Dispose(bool disposing) + 0x26a bytes    
    System.dll!System.ComponentModel.Component.Dispose() + 0x1b bytes   
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadWindows.Dispose() + 0xb3 bytes  
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.DisposeThreadWindows() + 0x12d bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(System.IntPtr dwComponentID, int reason, int pvLoopData) + 0x58e bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason = 4, System.Windows.Forms.ApplicationContext context = {System.Windows.Forms.Application.ModalApplicationContext}) + 0x593 bytes 
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x81 bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Form.ShowDialog(System.Windows.Forms.IWin32Window owner) + 0x765 bytes    
    Esfand.exe!Esfand.Program.Main(string[] a = {string[0]}) Line 51 + 0x10 bytes   C#
4

6 に答える 6

5

これにより、プログラム内のすべてのフォームで固有のエラーが発生します (たとえば、「ドラッグ アンド ドロップ イベント ハンドラを登録できません」)。

これは、コードの中心的な問題に対する強力なヒントです。RegisterDragDrop() ネイティブ関数は、AllowDrop プロパティが true に設定されているコントロールがある場合に呼び出されます。フォームのネイティブ ウィンドウが作成されるときに呼び出されます。残念ながら、64 ビット バージョンの Windows を使用していて、プログラムを 32 ビット モードで実行するように強制した場合、例外が発生するのは非常に悪い時期です。この回答の主題。

RegisterDragDrop() が失敗する正当な理由はほとんどありません。しかし、1つ。あなたのスニペットから、あなたが Program.cs をいじっていることは既にわかります。ボイラープレート バージョンは次のようになります。

static class Program {
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]                // <=== Here!!!
    static void Main() {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

重要なコード行に大きな矢印を付けました。[STAThread] 属性は、どの GUI プログラムにも不可欠です。COM を初期化し、プログラムのメイン スレッドをシングル スレッド アパートメントとして構成する必要があることを CLR に通知します。アパートメントは非常に重要な COM 実装の詳細であり、その範囲はこの回答を少し超えています。この属性がない場合、プログラムのメイン スレッドはマルチスレッド アパートメントである MTA に参加します。ドラッグ アンド ドロップ、クリップボード、シェル ダイアログなど、スレッド セーフではないコードの敵対的な場所。

属性の使用を忘れると、当惑するような例外が発生する可能性があります。リンクされた回答で説明されているように、開発マシンが64ビットバージョンのVistaまたはWin7、重要な瞬間に発生する例外に問題があるWindowsバージョンを起動する場合は特に悪い.

この問題がなく、推奨される方法を使用する適切なバージョンの Program.Main() メソッド:

    [STAThread]                // <=== Don't forget this
    static void Main() {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        using (var login = new LoginForm()) {
            if (login.ShowDialog() != DialogResult.OK) return;
        }
        Application.Run(new MainForm());
    }
于 2013-05-12T11:32:53.747 に答える
1

スレッド例外エラーがスローされているかどうかを確認してください。Application_ThreadException イベントに何かが表示されるかどうかを確認します。

static void Main()
{
    Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
    try
    {
        //Your existing code
    }
    catch (Exception ex)
    {
    }
}

private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
}

編集: 別のオプションは、作成中の newForm の所有者として MainForm を明示的に設定することです。

newForm.ShowDialog(MainForm);

所有者がデフォルトで閉じられたログインフォームに設定されているように感じます。これにより、新しいフォームが自動的に閉じられます

于 2013-04-21T06:06:05.743 に答える
0

フォームをクラス メンバーとして定義してみてください。関数内ではありません。

于 2013-05-13T07:19:36.237 に答える
0

私の理解では、フォームはアプリケーション コンテキスト内で実行する必要があります。

次の方法で、メイン コンテキストから複数のフォームを起動するコードを継承しました。

var form1 = Form1();
Application.Run(form1);

// form returns, check public method form.ButtonPushed etc
if (form.Button1Pushed)
{
    var form2 = Form2();
    Application.Run(form2);
}

これにより、いくつかのフォームが正常に起動されます。

とてもエレガントなやり方とは思えませんが、うまくいきます...

于 2013-05-14T16:06:46.657 に答える