0

グリッド ビューでデータを表示する Windows フォーム アプリケーションがあります。データは、バックグラウンド ワーカー スレッドから自動的に更新 (DB から取得) されています。したがって、クロススレッド参照を避けるために、バックグラウンド スレッドの DoWork メソッドで GridView.BeginInvoke() を呼び出し、メッセージのリストを渡します。ただし、デリゲート メソッドでは、メッセージ リストは空です。

GridView.invoke() を使用すると、messageList に値が含まれますが、「オブジェクトは現在別の場所で使用されています」という例外が発生することがあります。これは、非 UI スレッドで UI コントロールを参照することが原因であると考えられます。

どうすればこの問題を解決できますか?

    public delegate void AddMessagesDelegate(List<ClientMessage> tempMessageList);

    private void SearchWorkerDoWork(object sender, DoWorkEventArgs e)
    {
        List<ClientMessage> partList = new List<ClientMessage>();

        View.GridViewtMain.Invoke(new InvokeDelegate(ClearMessagesFromGrid));
        //View.GridViewtMain.BeginInvoke(new InvokeDelegate(ClearMessagesFromGrid));
        partList.AddRange(Model.LoadSearchResult());
        View.GridViewtMain.Invoke(new AddMessagesDelegate(AddMessagesToGrid), new object[] {partList});
        //View.GridViewtMain.BeginInvoke(new AddMessagesDelegate(AddMessagesToGrid), new object[] {partList});
        while (!isCancelled && (partList.Count > 0))
        {
            partList.Clear();
            partList.AddRange(Model.LoadSearchResult());
            View.GridViewtMain.Invoke(new AddMessagesDelegate(AddMessagesToGrid), new object[] {partList});
            //View.GridViewtMain.BeginInvoke(new AddMessagesDelegate(AddMessagesToGrid), new object[] {partList});
        }
    }

    private void ClearMessagesFromGrid()
    {
        messageDataSource.Clear();
    }

    private void AddMessagesToGrid(List<ClientMessage> tempMessageList)
    {
        View.GridViewMain.BeginDataUpdate();

        foreach (ClientMessage message in tempMessageList)
        {
            messageDataSource.Add(message);
        }
        View.GridViewMain.GridControl.DataSource = messageDataSource;           
        View.GridViewMain.EndDataUpdate();
    }
4

1 に答える 1

2
  partList.Clear();

問題のあるコードの代わりに機能するコードを投稿しました。Invoke ではなく BeginInvoke を想定します。partList.Clear() メソッドは、デリゲート ターゲットがリストを使用できるようになる前に、リストを空にします。BeginInvoke 呼び出しの後で、リストの新しいインスタンスを作成する必要があります。UI スレッドは、古いリストを問題なく使用できるようになりました。だいたい

    while (!isCancelled)
    {
        partList = new List<ClientMessage>();
        partList.AddRange(Model.LoadSearchResult());
        if (partList.Count == 0) break;
        View.GridViewtMain.BeginInvoke(new AddMessagesDelegate(AddMessagesToGrid), new object[] {partList});
    }
于 2011-03-25T13:51:32.603 に答える