C#コンパイルエラー:"呼び出しまたはBeginInvokeに呼び出すことはできません、制御までのウィンドウハンドルって作成されます。"
-
21-08-2019 - |
質問
まだ投稿問題について、委譲の更新テキストボックスを他の形式です。だったので答えを起こします。こちらは自分のコード:
形式コード:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Data.OleDb;
using System.Collections.Specialized;
using System.Text;
using System.Threading;
delegate void logAdd(string message);
namespace LCR_ShepherdStaffupdater_1._0
{
public partial class Main : Form
{
public Main()
{
InitializeComponent();
}
public void add(string message)
{
this.Log.Items.Add(message);
}
public void logAdd(string message)
{ /////////////////////////// COMPILER ERROR BELOW ///////////
this.Invoke(new logAdd(add), new object[] { message }); // Compile error occurs here
}////////////////////////////// COMPILER ERROR ABOVE ///////////
private void exitProgramToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
{
Form aboutBox = new AboutBox1();
aboutBox.ShowDialog();
}
private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
{
}
private void settingsToolStripMenuItem1_Click(object sender, EventArgs e)
{
settingsForm.settings.ShowDialog();
}
private void synchronize_Click(object sender, EventArgs e)
{
string message = "Here my message is"; // changed this
ErrorLogging.updateLog(message); // changed this
}
}
public class settingsForm
{
public static Form settings = new Settings();
}
}
ログインクラスのコード:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LCR_ShepherdStaffupdater_1._0
{
public class Logging
{
static Main mainClass = new Main();
static logAdd logAddDelegate;
public static void updateLog(string message)
{
logAddDelegate = mainClass.logAdd;
logAddDelegate(message);
}
}
}
コンパイルエラー:
InvalidOperationExceptionした 独自のレンダリングメカニズム-呼び出しまたはBeginInvoke 呼び出すことはできません、制御まで のウィンドウハンドルって作成されます。
いていこうという思いを込めてハンドルのログの項目が---しなかった。問題は少しも不思議じゃないないということをやってGoogleを検索 広 だ漠然とした答えなのです。
教えてください作成方法の取り扱いを呼び出すことに限ります。がなくお楽しみいただけますので、いつまでこのコードよりシンプルです。例えば、あまりないと思いますいつの追加機能...しなければいけなかったことがただ項目の呼び出しから、ログインクラスです。ありそいかがですか?
お!!!
編集:
私のプロジェクトはかなり大きめで、これらの項目のみがこの特定の問題です。
ログ 私RichTextBox1(ログにあります。ます。追加メッセージ))に名称変更でログインで簡単に確認のため再度ご入力.
私は呼び出しupdateLog(メッセージから別の形でつながったりもするのだけれど。長説明(テキスト)/質疑応答がここにあな違いが呼びかけupdateLog(メッセージからでも与えてくれるこのエラー)
だってものをもっと簡素化のために---を提供します。う必要はありませんの半分まで聞けばよかったのですが...ちこちら---少しも不思議じゃないとどのように関を呼び出す方法。私の研究は、ナメ出しているのですが---。
第二の編集:
と思い位置に問題がないからいいじゃないか初書きぐらい。
私のロギングクラスを使っているこのコードをmainClass:
静主mainClass=new Main();
私が作りたく新しい設計図のレプリカのメイン()を含む ログ (richtextboxうことにより更新)
呼び出updateLog(メッセージ)と思うよう心掛けておりますのLog(richtextbox)二体のMain()などmainClass.もちろん、そのまま捨てると私はこの例外がんでも見られるレプリカのメインを利用しています。
これは私の撮影のためには、細については、一般社団法人とした答え:
Main mainClass = Application.OpenForms.OfType<Main>().First();
logAddDelegate = mainClass.logAdd;
logAddDelegate(message);
いが必要mainClassないの()オペレーターがあまりないと思いますの作成の設計図を書こういうことができるように編集し、現在の形となりました。
上記のコードは動作しないものかも。でもC#構文?
まで上記のコードは、と思いを解決することができ問題と最後にちはこの問題は残り時間を求めるための答えなのです。
最終編集:
きっかけになるかもしれないとかげで、ユーザーです。ここでは私の更新をコード:
形式コード:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Data.OleDb;
using System.Collections.Specialized;
using System.Text;
using System.Threading;
delegate void logAdd(string message);
namespace LCR_ShepherdStaffupdater_1._0
{
public partial class Main : Form
{
private static Main mainFormForLogging;
public static Main MainFormForLogging
{
get
{
return mainFormForLogging;
}
}
public Main()
{
InitializeComponent();
if (mainFormForLogging == null)
{
mainFormForLogging = this;
}
}
public void add(string message)
{
this.Log.Items.Add(message);
}
public void logAdd(string message)
{
this.Log.BeginInvoke(new logAdd(add), new object[] { message });
}
private void exitProgramToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
{
Form aboutBox = new AboutBox1();
aboutBox.ShowDialog();
}
private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
{
}
private void settingsToolStripMenuItem1_Click(object sender, EventArgs e)
{
settingsForm.settings.ShowDialog();
}
private void synchronize_Click(object sender, EventArgs e)
{
add("test");
Logging.updateLog("testthisone");
//DatabaseHandling.createDataSet();
}
}
public class settingsForm
{
public static Form settings = new Settings();
}
}
ログインクラスのコード:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LCR_ShepherdStaffupdater_1._0
{
public class Logging
{
static Main mainClass = Main.MainFormForLogging;
static logAdd logAddDelegate;
public static void updateLog(string message)
{
logAddDelegate = mainClass.logAdd;
logAddDelegate(message);
}
}
}
解決
右、私は再び開始するつもりです。
何が起こっているのかを理解するためには、互いにどのように関連するか、.NETとWindowsを理解する必要があります。 .NETはWindows上で実行され、ウィンドウ、リストビュー、エディットボックス(標準テキストボックス用のWin32名)のようなネイティブのWin32概念の多くをラップします。これは、テキストボックスまたはフォームの有効な.NETのインスタンスを持っているが、まだその項目(エディット、またはウィンドウ)の基礎となる、Windowsのバージョンを持っていないことを意味します。 HandleCreatedがtrueの場合、アイテムのWindows版が作成されます。
何かがフォームのウィンドウが作成される前に呼び出されるlogAdd方法につながっているので、あなたの問題が発生しています。フォームのインスタンスがインスタンス化されていますが、ウィンドウハンドルが作成される前に、何かがlogAddを呼び出そうとした後、これはあなたの起動時にどこかを意味します。あなたはlogAddにブレークポイントを追加する場合は、その呼び出しを行っているかを見ることができるはずです。あなたが見つけることはコールが実際に実行されている主なあなたのロガークラスで作成するインスタンスとしないメインインスタンス上で行われているということです。ロガーインスタンスが示されることは決してありませんように、ウィンドウハンドルが作成されていない、ので、あなたがエラーを取得します。
アプリケーションが実行される一般的な方法は、プログラムのクラスで通常メインと呼ばれるスタートアップ方法でApplication.Run(新しいメインを())を呼び出すことです。あなたは、メインのこのインスタンスを指すようにロガーを必要とします。
があり、フォームのインスタンスを取得するにはいくつかの方法は、独自の注意点とそれぞれ、ですが、簡単にするために、あなたは、メインクラス自体をオフインスタンスを公開することができます。たとえばます:
public partial class Main : Form
{
private static Main mainFormForLogging;
public static Main MainFormForLogging
{
get
{
return mainFormForLogging;
}
}
public Main()
{
InitializeComponent();
if (mainFormForLogging == null)
{
mainFormForLogging = this;
}
}
protected void Dispose(bool disposing)
{
if (disposing)
{
if (this == mainFormForLogging)
{
mainFormForLogging = null;
}
}
base.Dispose(disposing);
}
}
他のヒント
私は次のメソッドを使用して、過去にこれを解決した。
private void invokeOnFormThread(MethodInvoker method)
{
if (IsHandleCreated)
Invoke(new EventHandler(delegate { method(); }));
else
method();
}
の代わりに呼び出しのコールinvokeOnFormThread
。ハンドルがすでに作成されている場合にのみ、それ以外の場合は、呼び出し側のスレッドを使用しますが、フォームのスレッドを使用します。
、それはほとんど常にあなたはそれが実際に作成された前のコントロールまたはフォームに作用しようとしたことを意味します。
メモリ内のクラスとして、オペレーティングシステム内のエンティティとして:リサイズにおいて、GUI要素は、2つの半独立した寿命を有します。このように、それは実際にはまだ作成されていない.NETでコントロールを参照することが可能です。 「作成されるハンドル」プログラムは、そのプロパティを操作することを可能にするOSによる制御に割り当てられた番号を有することをいう。
この場合には、ほとんどのエラーは、フォームのLoadイベントの終了時にフラグを設定のみそのフラグがセットされた後、フォームのコントロールを操作しようとすることによって排除することができる。
これは、実行時エラーではなく、コンパイラエラーです。
フォーム、「主」、あなたはBeginInvokeメソッドへの呼び出しを行うか、それを呼び出すことができます前に、表示された(したがって、ウィンドウハンドルが作成)する必要があります。
私は通常、このような状況でやっていることは、それはBeginInvokeメソッドまたは呼び出しへの呼び出しを使用する必要があるかどうかを判断するためのフォームにそれを残しています。あなたはInvokeRequired(MSDNをチェック)を呼び出してそれをテストすることができます。
まず第だから、私はLogginクラスのupdateLogメソッドでlogAddDelegate呼び出しを取り除くと思います。ただ、ログを追加するためのフォームにまっすぐ電話をかけます。これと同様ます:
public partial class Main : Form
{
public Main()
{
InitializeComponent();
}
private delegate void AddNewLogMessageEventHandler(string message);
public void AddLogMessage(string message)
{
object[] args = new object[1];
args[0] = message;
if (InvokeRequired)
BeginInvoke(new AddNewLogMessageEventHandler(AddLog), args);
else
Invoke(new AddNewLogMessageEventHandler(AddLog), args);
}
private void AddLog(string message)
{
this.Log.Items.Add(message);
}
}
}
あなたが見ることができるように、、フォーム自体は、それが非同期かないメソッドを呼び出す必要があるかどうかを決定する担当しています。
フォームへの呼び出しを作っているので、そのが表示されて前にしかし、これはまだ、あなたのランタイムエラーが修正されません。あなたは、フォームのハンドルがnullであるかどうかを確認することができ、それは、少なくとも、あなたが有効なフォームを扱っているかどうかを確認することができます。
というエラーは、あなたがまだ「示す」されていないウィンドウを呼び出す場合に発生する傾向があります。あなたはロギングクラス(具体的には、第1ライン)でコードをメインクラスの2番目のインスタンスを作成していませんか?それはあなたがログオン呼び出しているメインフォームは、あなたが見ているメインフォームではないことかもしれません。あなたがチェックしたい場合は、ちょうどあなたのロギングコール内部「MainClass.Show()」の呼び出しを追加します。あなたがポップアップメインフォームの2番目のコピーを取得した場合、問題はあなたのロギングクラスは、フォームの右の「インスタンス」を参照していないということです。
「青写真」としてクラスを考えます。 (単語「新しい」で作成した)クラスの各インスタンスは、設計図から作成され、他の目的です。 (この場合は、お使いの二つの主要な形式)2つのオブジェクトが同じ青写真を共有するという理由だけで、あなたは、互換的にそれらを使用できることを意味するものではありません。この場合、あなたはすでにメインフォームを持っている、とあなたはそれを「再利用」したいです。あなたが試すことができます:
MainClass myMainForm = Application.OpenForms.OfType<MainClass>().First();
logAddDelegate = myMainForm.logAdd;
logAddDelegate(message);
の代わりにあなたが現在持っているもののあなたのログ機能の内部。違いは)Application.OpenForms.OfTypeへの呼び出し(ということである。まず、あなたのアプリケーションに行き、あなたが見ている実際メインフォームを取得(技術的には、それはそれの最初のインスタンスを取得します)、その上で、あなたの呼び出しを行います直接、形成します。
この情報がお役に立てば幸いです。
これは、他の人がこれに巻き込まれた場合に支援することです。 私の問題: VB.net:「ウィンドウハンドルが作成されるまで呼び出しまたはBeginInvokeをコントロール上で呼び出すことはできません。」 私はイベントのハンドラを持つフォームを閉じたイベントのハンドラを削除せずに、デリゲートを更新するために呼び出しています。
私がやった:私は、フォームを閉じると、私はすべてのハンドラを削除し、私は、フォームを開いたときにそれらをバック割り当て。これは、問題を解決します。
logAddDelegate(メッセージ);
私は、Form_Loadイベントが提起されている前に、あなたはこれを呼び出していると思います。フォームがlogAddDelegate(...)を呼び出す前にロードするようにするために、すなわち呼び出す前に待機するようにコードを修正しLogging.updateLog()
これはあなたの正確なコードですか?あなたのアドオン(String)メソッドにthis.Log.Items.Add(message);
を呼び出しているが、あなたのロギングクラスはログインしていない、ロギングと呼ばれています。あなたはおそらく、ログと呼ばれる別のフォームを持っていますか?あなたがaddメソッドを呼び出したときにそのフォームが作成されていない場合は、この例外が発生します。
私はInvokeRequired
が信頼性がないことが判明したので、私は単純に使用
if (!this.IsHandleCreated)
{
this.CreateHandle();
}