简体   繁体   English

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

[英]BeginInvoke not passing data but using Invoke causes exception

I have a windows forms application that shows data in a grid view. 我有一个Windows窗体应用程序,在网格视图中显示数据。 The data is being automatically refreshed (fetched from a DB) from a background worker thread. 数据将从后台工作线程自动刷新(从数据库中获取)。 So to avoid any cross thread references, in the DoWork method of the background thread, I call GridView.BeginInvoke() and pass the list of messages. 因此,为了避免任何交叉线程引用,在后台线程的DoWork方法中,我调用GridView.BeginInvoke()并传递消息列表。 But in the delegate methods, the message list is empty. 但在委托方法中,消息列表为空。

If I use GridView.invoke(), the the messageList does contain the values, but sometimes there is an exception which says "object is currently in use elsewhere" which I believe is caused due to referencing UI control on a non-UI thread. 如果我使用GridView.invoke(),则messageList确实包含值,但有时会出现一个异常,说“对象当前正在其他地方使用”,我认为这是由于在非UI线程上引用UI控件引起的。

How can I solve this problem? 我怎么解决这个问题?

    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();
    }
  partList.Clear();

You posted the code that works instead of the code you have a problem with. 您发布了有效的代码,而不是您遇到问题的代码。 I'll assume BeginInvoke instead of Invoke. 我将假设BeginInvoke而不是Invoke。 The partList.Clear() method is going to empty the list, before the delegate target can use the list. 在委托目标可以使用列表之前 ,partList.Clear()方法将清空列表。 You should create a new instance of the list after the BeginInvoke call. 您应该在BeginInvoke调用之后创建列表的新实例。 The UI thread can now work with the old list without trouble. UI线程现在可以毫无困难地使用旧列表。 Roughly 大致

    while (!isCancelled)
    {
        partList = new List<ClientMessage>();
        partList.AddRange(Model.LoadSearchResult());
        if (partList.Count == 0) break;
        View.GridViewtMain.BeginInvoke(new AddMessagesDelegate(AddMessagesToGrid), new object[] {partList});
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM