BeginInvoke не передает данные, но использование Invoke вызывает исключение

У меня есть приложение Windows Forms, которое показывает данные в виде сетки. Данные автоматически обновляются (извлекаются из БД) из фонового рабочего потока. Поэтому, чтобы избежать перекрестных ссылок, в методе DoWork фонового потока я вызываю GridView.BeginInvoke() и передаю список сообщений. Но в методах делегата список сообщений пуст.

Если я использую GridView.invoke(), messageList действительно содержит значения, но иногда возникает исключение, в котором говорится, что «объект в настоящее время используется в другом месте», что, как я полагаю, вызвано ссылкой на элемент управления пользовательского интерфейса в потоке, отличном от пользовательского интерфейса.

Как я могу решить эту проблему?

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

person EndlessSpace    schedule 25.03.2011    source источник


Ответы (1)


  partList.Clear();

Вы разместили код, который работает вместо кода, с которым у вас возникли проблемы. Я предполагаю, что BeginInvoke вместо Invoke. Метод partList.Clear() очистит список, прежде чем цель делегата сможет использовать список. Вы должны создать новый экземпляр списка после вызова BeginInvoke. Поток пользовательского интерфейса теперь может без проблем работать со старым списком. Грубо

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