1

WinFormsを使用してC#のVisual Studio 2010.NET4.0で作業しています。

DataGridViewフォームには、にバインドされたデータであるシングルがありますDataSet

は、から読み取られているデータを処理しDataSetているから入力されています。ThreadConcurrentQueue

このコードは、セマフォを使用してへのアクセスをシリアル化します。DataSetこれは、「ワーカー」スレッドとUIメインスレッド(更新時DataGridView)からアクセスできるためです。

UI /フォームには、System.Windows.Forms.Timer1/4秒ごとに起動DataGridViewして、の現在の内容でを更新する関数を呼び出す機能がありDataSetます。

DataGridViewデータがスクロールしてスクロールバーが表示されるまで、コードは正しく実行されます。この時点で、フォーム全体が応答しなくなります。タイトルのキャプションには「プログラムが応答していません」と表示されます。

興味深いのは、デバッガーで実行している間はこれが発生しないことです。プログラムがデプロイされている場合のみ。そして、例外は発生しません。

動作を変更せずに、InvokeとBeginInvokeの両方を使用してみました。

質問:

1-以下の私のコードの何が問題になっている可能性がありますか?
2-デバッガーで実行している間はこの動作を観察できないので、問題の原因を特定するにはどうすればよいですか?

コードの壁を以下に示します。たくさんのコードがあることは知っていますが、できる限り切り取っています。

// deleted using statements for brevity

namespace namcom
{
    public partial class wndXMLtrans : Form
    {
        private DataSet dsRecords = new DataSet();
        private Thread threadConsumeXML = null;
        private static Semaphore ResourceLock;

        public wndXMLtrans(String ip)
        {
            InitializeComponent();
            ResourceLock = new Semaphore(1, 1);
            curSize = this.Size;
            m_ip = ip;
        }

        private Boolean AddRowToDataSet(String[] columns, String xml)
        {
            Boolean retCode = true;
            String value = String.Empty;
            Int64 id = -1;
            DataRow row;

            ResourceLock.WaitOne();
            row = dsRecords.Tables[0].NewRow();

            // prepare row code omitted - brevity

            // add new data row to DataSet
            dsRecords.Tables[0].Rows.Add(row);
            ResourceLock.Release();
            // SQL inserts into DB removed - brevity
            return (retCode);
        }

        private Boolean HandleSingleXMLMessage(String[] columns, String xml, out String exceptionMessage)
        {
            Boolean boolRet = true;
            exceptionMessage = String.Empty;

            // store data in dataset and database
            if ( closeRequested == false  )
            {
                AddRowToDataSet(columns, xml);
            }
            return (boolRet);
        }

        private Boolean StoreG2SMessages(String message)
        {
            // code removed - brevity
            // removed code just parses out string and in a loop calls HandleSingleXMLMessage
            // until all XML in message have been processed
            HandleSingleXMLMessage(columns,xml, out exceptionMessage)  // call in loop
            return (ret);
        }

        // pull XML out of mainwnd.msgQueue and update database
        private void G2SParseThread()
        {
            String Data;
            String exceptionMsg = String.Empty;

            while ( /* thread is to be active - code removed for brevity */)
            {
                Data = String.Empty;
                if (mainwnd.msgQueue.TryDequeue(out Data) == true)
                {
                    this.StoreG2SMessages(Data);
                }
                Thread.Sleep(20);
            }
            // thread ended cleanup code removed - brevity
        }


        private void StartThreads()
        {
            // start XML packet processing thread
            threadConsumeXML = new Thread(G2SParseThread);
            threadConsumeXML.SetApartmentState(ApartmentState.STA);
            threadConsumeXML.Start();

            threadMonitor = new Thread(() => threadHandleStatusMsg(ref mainwnd.statusQueue));
            threadMonitor.Start();
        }


        private void wndXMLtrans_Shown(object sender, EventArgs e)
        {
            // remove SQL code - brevity
            // fill dsRecords ( DataSet )
            try
            {
                var adapter = new SQLiteDataAdapter(selectSQL, dbConnection);
                adapter.Fill(dsRecords);
                dataGrid.DataSource = dsRecords.Tables[0].DefaultView;
                adapter.Dispose();
            }
            catch { } // catch code removed - brevity
            StartThreads();
        }

        private void gridUpdateTimer_Tick(object sender, EventArgs e)
        {
            ResourceLock.WaitOne();
            try
            {
                if (dataGrid != null && numRows < dsRecords.Tables[0].Rows.Count)
                {
                    if (dataGrid.RowCount > 0)
                    {
                        dataGrid.FirstDisplayedScrollingRowIndex = dataGrid.RowCount - 1;
                    }
                    dataGrid.Refresh();
                    numRows = dsRecords.Tables[0].Rows.Count;
                }
            }
            catch { }
            ResourceLock.Release();
        }
    }
}

DataSet編集:ハンスは、ワーカースレッドからバウンドを更新できないという答えを提供しました。そこで、以下を追加することで問題を解決することができました。

これらは、Invokeを使用してデリゲート関数によって呼び出されます。更新前に呼び出されたバインドを解除DataSetし、更新後にバインドしDataSetます。これは機能DataGridViewしますが、がちらついたり、何度も再描画されたりするように見えます。これを改善する方法はありますか?

public void UnbindDataGridView(DataGridView grid)
{
    grid.DataSource = null;
}

public void BindDataGridView(DataGridView grid)
{
    grid.DataSource = dsRecords.Tables[0].DefaultView;
}
4

0 に答える 0