BeginInvoke不传递数据但使用Invoke会导致异常

时间:2011-03-25 13:43:01

标签: c# winforms multithreading invoke begininvoke

我有一个Windows窗体应用程序,它在网格视图中显示数据。数据将从后台工作线程自动刷新(从数据库中获取)。因此,为了避免任何交叉线程引用,在后台线程的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();
    }

1 个答案:

答案 0 :(得分:2)

  partList.Clear();

您发布了有效的代码,而不是您遇到问题的代码。我将假设BeginInvoke而不是Invoke。 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});
    }