4

私はこのようなコードを持っています:

private void testToolStripMenuItem_Click(object sender, EventArgs e)
{
    toolStripStatusLabel1.Text = " Device Testing...";

    positive = false;

    clearsensors_gui();
    datarec = false;
    cmd = 04;
    datarec = serialport_FT(0, 1);

    if (datarec)
    {
        char ab = Convert.ToChar(rec_data[1]);
        //MessageBox.Show("\n" + ab + "\n");
        int cab = Convert.ToInt16(ab);
        int cabc1 = cab & 1;
        int cabc2 = cab & 2;
        int cabc3 = cab & 4;
        int cabc4 = cab & 8;
        int cabc5 = cab & 16;
        int cabc6 = cab & 32;

        if (cabc1 == 1)
            ovalShape1.FillColor = Color.Green;
        else
            ovalShape1.FillColor = Color.Red;

        if (cabc2 == 2)
            ovalShape2.FillColor = Color.Green;
        else
            ovalShape2.FillColor = Color.Red;

        if (cabc3 == 4)
            ovalShape3.FillColor = Color.Green;
        else
            ovalShape3.FillColor = Color.Red;

        if (cabc4 == 8)
            ovalShape4.FillColor = Color.Green;
        else
            ovalShape4.FillColor = Color.Red;

        if (cabc5 == 16)
            ovalShape5.FillColor = Color.Green;
        else
            ovalShape5.FillColor = Color.Red;

        if (cabc6 == 32)
            ovalShape6.FillColor = Color.Green;
        else
            ovalShape6.FillColor = Color.Red;

        toolStripStatusLabel1.Text = " Device Tested";
    }
    else
    {
        toolStripStatusLabel1.Text = "Try Again or Communication With Device Failure....";
    }
}

上記のコードは、センサーを読み取るためのものです。つまり、datarec = serialport_FT(0、1); 関数は、GUI側でセンサー出力を提供します。これは、後でred \ green ovalShapeX(1-6)で示されます。

質問:datarec = serialport_FT(0, 1);この関数はliltimeを使用するため、GUIはその時間までフリーズします。これを回避するにはどうすればよいですか?

バックグラウンドワーカーを使用しようとしましたが、このプロセス全体を配置する場所がわかりませんでした。また、ovalShapeに移動してそのプロパティを変更すると、クロススレッド操作エラーが発生しました。

関数のどの部分をバックグラウンドで使用するのか、いつどこで1番目のスレッドに戻るのかがわかりません。

スレッドを使用する必要がある場合は、backgroundworkerを使用するか、invokeを使用するのを手伝ってください

4

5 に答える 5

12

あなたはこのようなことをすることができます:

toolStripStatusLabel1.Text = " Device Testing...";
positive = false;
clearsensors_gui();
datarec = false;
cmd = 04;

BackgroundWorker worker = new BackgroundWorker();

worker.DoWork += delegate(object s, DoWorkEventArgs args)
{
    // Will be run on background thread
    args.Result = serialport_FT(0, 1);
};

worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
{
    bool result = (bool)args.Result;

    if (result)
    {
        // Do your UI updates here
    }
};

worker.RunWorkerAsync();

1つの改善点は、args.Resultのタプルとしてdatarec結合することです。rec_data

于 2012-06-26T08:28:02.507 に答える
2

バックグラウンドワーカーでは、DoWorkイベントを使用します。

worker.DoWork += new DoWorkEventHandler(yourEventHandler); 

void yourEventHandler(object sender, DoWorkEventArgs e)
{
//your work here
}
于 2012-06-26T08:19:36.153 に答える
1

WinFormsを使用しているので、アプリケーションで複数のスレッドを使用するための優れたMSDN記事を次に示します。.NETベースのアプリケーションに複数のスレッドを備えた高速でレスポンシブなUIを提供する

この記事は「数日前」ですが、原則は今日でも絶対に有効です。

.NET 4.xバージョンで作業している場合は、タスク並列ライブラリを使用して、複数のスレッドでの作業を簡単にすることもできます。

今後の.NET4.5は、さらに快適なawaitおよびasycキーワードも提供します:AsyncおよびAwaitを使用した非同期プログラミング

于 2012-06-26T08:29:31.103 に答える
0

すでに試したように(または、さらに良いのはTask )、これをバックグラウンドスレッドに入れますが、GUI関連の操作はControl.Invoke(WinFormsの場合)またはDispatcher.Invoke(WPFの場合)からのみ呼び出すように注意してください。

于 2012-06-26T08:22:48.893 に答える
0

タスクの進行に応じてリアルタイムで更新されるラベルを使用しました。[BackGroundWorkerを使用して]このコードを試すことができます。DoWorkビジネスロジックを配置する場所を確認し[コードの使用法を参照] BusinessClassProgressChangedタスクの進行中にバックグラウンドタスクがUIにリアルタイムで通知する場所を確認し、最後にRunWorkerCompleted、タスクの完了、エラー、またはキャンセル後にコードを処理する場所を確認します。

using System.ComponentModel;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form3 : Form
    {
        private BackgroundWorker _worker;
        BusinessClass _biz = new BusinessClass();
        public Form3()
        {
            InitializeComponent();
            InitWorker();
        }

        private void InitWorker()
        {
            if (_worker != null)
            {
                _worker.Dispose();
            }

            _worker = new BackgroundWorker
            {
                WorkerReportsProgress = true,
                WorkerSupportsCancellation = true
            };
            _worker.DoWork += DoWork;
            _worker.RunWorkerCompleted += RunWorkerCompleted;
            _worker.ProgressChanged += ProgressChanged;
            _worker.RunWorkerAsync();
        }


        void DoWork(object sender, DoWorkEventArgs e)
        {
            int highestPercentageReached = 0;
            if (_worker.CancellationPending)
            {
                e.Cancel = true;
            }
            else
            {
                double i = 0.0d;
                int junk = 0;
                for (i = 0; i <= 199990000; i++)
                {
                    int result = _biz.MyFunction(junk);
                    junk++;

                    // Report progress as a percentage of the total task.
                    var percentComplete = (int)(i / 199990000 * 100);
                    if (percentComplete > highestPercentageReached)
                    {
                        highestPercentageReached = percentComplete;
                        // note I can pass the business class result also and display the same in the LABEL  
                        _worker.ReportProgress(percentComplete, result);
                        _worker.CancelAsync();
                    }
                }

            }
        }

        void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                // Display some message to the user that task has been
                // cancelled
            }
            else if (e.Error != null)
            {
                // Do something with the error
            }
        }

        void ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            label1.Text =  string.Format("Result {0}: Percent {1}",e.UserState, e.ProgressPercentage);
        }
    }

    public class BusinessClass
    {
        public int MyFunction(int input)
        {
            return input+10;
        }
    }
}
于 2012-06-26T08:29:11.107 に答える