2017-09-29 6 views
1

私はguiとリッチテキストボックスを持つアプリケーションを持っています。ここでは、データ処理がかなり長くなる可能性があるため、プログラムが現在行っていることを出力します。私はちょうど罰金以下のコードを呼び出すことができますBackgroundWorkerの方法でbackgroundworkerによって呼び出されたメソッド内からのプロセスの更新C#

1:

私はそのための2つのアプローチを試してみました

GlobalVar.backgroundWorkerAppendText = task.Build_CSV_List(); 
Processchange(); 

私が原因でない静的にヘルパークラスでForm1.Processchange();を使用することはできませんのに対しコンテキスト

2私は非常に最初のイベントハンドラを作成しようとしました。
アイデアはhelper.UpdateConsoleは()イベント

public event EventHandler OnConsoleUpdate; 
public void Consoleupdate() 
{ 
    OnConsoleUpdate(this, EventArgs.Empty); 
} 

を上げることだったのBackgroundWorkerがリッスンして、残念ながら、これが成功しなかったし、そのコンテキスト

public void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    StandardTasks task = new StandardTasks(); 
    Helper helper = new Helper(); 
    helper.OnConsoleUpdate += Processchange; 
    task.DoSomeStuffHere() 
} 
public void Processchange(object sender=null, EventArgs e=null) 
{ 
    //MessageBox.Show(GlobalVar.backgroundWorkerAppendText); 
    GlobalVar.next = false; 
    backgroundWorker1.ReportProgress(1); 
    while (GlobalVar.next == false) 
    { 
     helper.TimeBreaker(100,"ms"); 
    } 
} 

からProcesschangeを呼び出すします。イベントが起きるとすぐに私はエラーのメッセージSystem.NullReferenceExceptionを取得します。その後、私たちはグーグル・グーグルでイベント事件に付随する犯人がいないという結論に至りました。

編集:OnConsoleUpdate()== nullのヘルパーは

event = null

下のスクリーンショットに示すように解決するために重要であるかもしれない別のクラスファイル「ヘルパー」です。

私はあなたが私を助けてくれることを願っています。

+0

タスクベースの非同期パターンに切り替えるオプションです(TAP)?それから、ThreadPoolでTaskを開始し、Progressオブジェクトに渡すことができます。 Backgroundworkerを使いたい場合は、関連するコードをさらに表示する必要があります。 – Fildor

+0

このバックグラウンドワーカーをどこから始めましたか?私はそれのような何かをしています:backgroundWorker1.RunWorkerAsync(); – Arkadiusz

+0

ところで、いくつかのコードの臭いがある "GlobalVar"クラスを持っています... – Fildor

答えて

2

ようこそ!

すぐに気がついたことがいくつかあります。

まず、イベントの問題を解決しましょう。あなたは正しいアプローチを持っています - それを呼び出すにはイベントとメソッドが必要ですが、そのメソッドはイベントがnullであるかどうかをチェックする必要があります。

public event EventHandler OnConsoleUpdate; 
public void ConsoleUpdate() 
{ 
    OnConsoleUpdate?.Invoke(this, EventArgs.Empty); 
} 

上記?、ヌル・条件演算子を使用しています:基本的に

は、これを行います。あなたはそれについての詳細を読むことができますon this MSDN page

2番目のこと...あなたのバックグラウンドワーカーが実際に何をしているのかは不明です。それはあなたが作ったカスタムクラスのようなものですね?それが重要な理由は、.NETが実際に操作を実行するために使用されるBackgroundWorkerクラスを持っているからです...よく、バックグラウンドで。また、OnProgressChangedイベントがあり、これを使用してUIを更新できます(WorkerReportsProgressプロパティをtrueに設定することを忘れないでください)。上記のBackgroundWorkerを使用するには、自分でイベントを作成する必要はありません。

標準の使用方法は次のとおりです。NET BackgroundWorker

System.ComponentModel.BackgroundWorker worker = new System.ComponentModel.BackgroundWorker(); 

void StartBackgroundTask() 
{ 
    worker.DoWork += worker_DoWork; 
    //if it's possible to display progress, use this 
    worker.WorkerReportsProgress = true; 
    worker.ProgressChanged += worker_ProgressChanged; 
    //what to do when the method finishes? 
    worker.RunWorkerCompleted += worker_RunWorkerCompleted; 
    //start! 
    worker.RunWorkerAsync(); 
} 

void worker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) 
{ 
    //perform any "finalization" operations, like re-enable disabled buttons 
    //display the result using the data in e.Result 
    //this code will be running in the UI thread 
} 

//example of a container class to pass more data in the ReportProgress event 
public class ProgressData 
{ 
    public string OperationDescription { get; set; } 
    public int CurrentResult { get; set; } 
    //feel free to add more stuff here 
} 

void worker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) 
{ 
    //display the progress using e.ProgressPercentage or e.UserState 
    //this code will be running in the UI thread 
    //UserState can be ANYTHING: 
    //var data = (ProgressData)e.UserState; 
} 

void worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) 
{ 
    //this code will NOT be running in the UI thread! 
    //you should NOT call the UI thread from this method 

    int result = 1; 
    //perform calculations 
    for (var i = 1; i <= 10; i++) 
    { 
     worker.ReportProgress(i, new ProgressData(){ OperationDescription = "CustomState passed as second, optional parameter", CurrentResult = result }); 
     System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5)); 
     result *= i; 
    } 

    e.Result = result; 
} 

は今、BackgroundWorkerクラスについての事は、それがかなり古いことで、現在の.NETバージョンで、あなたは簡単にバックグラウンド処理とUIの更新を処理するためにasync/awaitキーワードを使用することができますが、これはおそらくですこの質問の範囲外に行く。つまり、async/awaitの存在は、その使用が非常に簡単なBackgroundWorkerの使用を無効にしません。

あなたのコードにもう一つ気になることがあります。

public void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    StandardTasks task = new StandardTasks(); //<- you create a task 
    Helper helper = new Helper(); // <- you create a helper 
    helper.OnConsoleUpdate += Processchange; // <- you hook up to the helper event 
    task.DoSomeStuffHere(); // <- you do stuff with the task... but the task doesn't know about your helper above! Does `StandardTasks` use `Helper`? If so, how? 
} 

static以外のイベントは、グローバルではありません。したがって、クラスの1つのインスタンスでイベントに接続しても、そのクラスの別のインスタンスはそのイベントを「起動」しません。あなたの問題を解決する一つの方法は、StandardTasksクラスは、コンストラクタのパラメータの1つとしてHelperを取る作ることであろうと思われるので、コードは次のようになります。

Helper helper = new Helper(); // <- you create a helper 
helper.OnConsoleUpdate += Processchange; // <- you hook up to the helper class event to actually do something 
StandardTasks task = new StandardTasks(helper); //<- you create a task which will use the helper with the hooked up event above 
+0

を参照してください。このようなnullのイベントハンドラを確認することは安全ではなく、例外が発生する可能性があります。追加されたハンドラはnullのチェックとハンドラの呼び出しの間で削除されます。 null条件付き演算子(?)を使用するか、またはOnConsoleUpdateをローカル変数に保存し、nullチェックと呼び出しにそれを使用することをお勧めします。 –

+1

@SzabolcsDézsiあなたは間違いなしです。私は答えを編集します。だが、公平になるためには、その前にイベントを処理する標準的な方法がありましたか?オペレータが追加されたと私は信じています... – Shaamaan

+0

こんにちはShaamaan、あなたの助けに感謝します。あなたのコードは実際には私のコードで持っているが動作していないです。バックグラウンドワーカーのために、私はフォームデザイナーのツールウィンドウから "引っ張った"。私はProcesschangedを行うこともできますが、バックグラウンドワーカーから直接行うことができます。それは呼び出したメソッドからではありません。 –

関連する問題