-1

私は最近、プロトタイプの c# コンソール アプリケーションを作成して、4 つの計測器からの測定値を並行して (同じ上でTimeStamp) 読み込みます。これには、parallel.invoke コマンドを使用しました。結果は毎回非常に良好でした。Winforms後で、を使用して同じ概念を実装しようとしましたbackgroundworker。したがって、私DoWorkはこれを呼び出して、4つの関数を実行して読み取り値を取得しましたが、結果が返されてから時間が経ち、タイムスタンプが同じではありません。バックグラウンドワーカーなしで試してみましたが、同じ結果が得られました。なぜ parallel.invoke がそのように動作しているのか、誰にもわかりますか? winform ではなく、コンソール アプリケーションで正常に動作することを確認します。また、複数であることを確認する方法はありますかasync procces実行は並行して実行されますか? これを理解するのに苦労しています。ここで私を助けてください。コメントをいただければ幸いです。

更新:混乱して申し訳ありませんが、以前に並列呼び出しでこれを行った後、タスクに変更しましたが、動作は同じです。

コンソール アプリケーション:

public static void funcc()
{
    for (int i = 0; i < 5; i++)
    {
        rawData3 = fmio.IO.Read(4 * numReadings);
        RawData3.Add(rawData3);
    }
}

public static void funcd()
{
    for (int i = 0; i < 5; i++)
    {
        rawData4 = fmio.IO.Read(4 * numReadings);
        RawData4.Add(rawData4);
    }
}

static void Main(string[] args)
{
    //Parallel.Invoke(() => { funcb(); }, () => { funcc(); }, () => { funca(); }, () => { funcd(); });       

    var factory = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.None);

    Task t1 = factory.StartNew(funca);
    Task t2 = factory.StartNew(funcb);
    Task t3 = factory.StartNew(funcc);
    Task t4 = factory.StartNew(funcd);

    t1.Wait();
    t2.Wait();
    t3.Wait();
    t4.Wait();

    WriteToFile(); // Writes Result to the file
}

私のGuiアプリケーションbackgroundWorkerでは、GUIアプリケーションで使用している上記で定義したものと同じ読み取り関数を使用してこれを行っています:

public static void funca()
{
    for (int i = 0; i < 5; i++)
    {
        rawData = fmio.IO.Read(4 * numReadings); // Getting Data in Byte Array
        RawData1.Add(rawData);                   // Putting it in ArrayList
    }
}

public static void funcb()
{
    for (int i = 0; i < 5; i++)
    {
        rawData2 = fmio.IO.Read(4 * numReadings);
        RawData2.Add(rawData2);
    }
}

private void btn_StartMeasurement_Click(object sender, EventArgs e)
{
    if (!bwObj.IsBusy)
    {
        bw_Obj.RunWorkerAsync();
    }
}

private void bw_Obj_DoWork_1(object sender, DoWorkEventArgs e)
{
    //Parallel.Invoke(() => { funcb(); }, () => { funcc(); }, () => { funca(); }, () => { funcd(); });

    var factoryA = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.None);
    var time = System.Diagnostics.Stopwatch.StartNew();
    Task t1 = factoryA.StartNew(() => funca(Globls.numReadings, DMM));
    Task t2 = factoryA.StartNew(() => funcb(Globls.numReadings, DMM2));
    Task t3 = factoryA.StartNew(() => funcc(Globls.numReadings, DMM3));
    Task t4 = factoryA.StartNew(() => funcd(Globls.numReadings, DMM4));

    t1.Wait();
    t2.Wait();
    t3.Wait();
    t4.Wait();

    WriteToFile();
}
4

2 に答える 2

0

この問題を次のように処理します。独自のクラスで動作する並列読み取りコードを抽出し、コンソール アプリケーションwinforms アプリケーションのstatic両方から呼び出して、何が起こるかを確認します。両方の方法で動作するか、まったく機能しないものがあることに気付くはずです (同じコードを呼び出しているため)。

于 2012-07-10T10:34:39.867 に答える
0

これは多くの方法で実装できます。bw_Obj_DoWork_1 セクションにあるものを並行して実行する場合は、btn_StartMeasurement_Click を変更して BackgroundWorker を削除することを検討します。

private void btn_StartMeasurement_Click(object sender, EventArgs e)
{
    Task[] tasks = new Task[]
        {
            Task.Factory.StartNew(funca),
            Task.Factory.StartNew(funcb),
            Task.Factory.StartNew(funcc),
            Task.Factory.StartNew(funcd)
        };
    Task writeTask = Task.Factory.ContinueWhenAll(tasks, (t) => writeToFile());
}

または、メソッドを作成することもできます。私はそれを executeAndWrite と呼び、btn_StartMeasurement_Click でスレッドまたはタスクを使用してそれらを開始します。

private void btn_StartMeasurement_Click(object sender, EventArgs e)
{
    new Thread(executeAndWrite).Start();
}

private void executeAndWrite()
{
    Parallel.Invoke(funca, funcb, funcc, funcd);
    writeToFile();
}

私は個人的にこのオプションを使用します。

于 2013-03-25T02:32:42.977 に答える