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

发布于 2024-10-25 21:33:48 字数 1848 浏览 1 评论 0原文

我有一个 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();
    }

I have a windows forms application that shows data in a grid view. 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. 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.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

冰魂雪魄 2024-11-01 21:33:48
  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});
    }
  partList.Clear();

You posted the code that works instead of the code you have a problem with. I'll assume BeginInvoke instead of Invoke. The partList.Clear() method is going to empty the list, before the delegate target can use the list. You should create a new instance of the list after the BeginInvoke call. The UI thread can now work with the old list without trouble. 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});
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文