如何在GUI事件中访问System.Timers.Timer中创建的对象

时间:2021-02-23 20:38:20

I'm using a System.Timers.Timer to get a PrintQueueCollection every N-seconds so I'm always up to date if something changed. The timer sends a RefreshEvent with the PrintQueue so I can handle changes in my Gui.

我正在使用System.Timers.Timer来每隔N秒获取一次PrintQueueCollection,所以如果发生变化,我总是最新的。计时器发送带有PrintQueue的RefreshEvent,这样我就可以处理我的Gui中的更改。

Here's the Refresh function, the timer calls every n-seconds

这是刷新功能,定时器每隔n秒调用一次

private void Refresh()
{
    lock (_locker)
    {
        try
        {
             // _server == ServerName if isNullOrEmppty it's localhost
            PrintServer printServer = new PrintServer(_server);
            PrintQueueCollection printQueueCollection = printServer.GetPrintQueues();

            foreach (PrintQueue pq in printQueueCollection)
            {
                if (_firstRun) break;

                // List of Unique Printernames so not all printers get 'refreshed'
                if (_printersToMonitor.Contains(pq.Name))
                {
                    var currentPrinter = new Printer(pq);
                    // Event catched in Gui
                    Refreshed?.Invoke(currentPrinter);
                }
            }
        }
        catch (Exception)
        {
            //...
        }
    }
}

The Event is catched in a Control this way

事件以这种方式在Control中捕获

// Printer is a Wrapper class that contains the PrintQueue and several other information I need e.g. results of SNMP walks
private void RefreshPrinter(Printer printer)
{
    if (_localPrinters.Count == 0)
        Dispatcher.Invoke(() => _localPrinters.Add(printer));
    else
    {
        // _localPrinters is a ObservableCollection<Printer> Bound to gui
        foreach (Printer p in _localPrinters.ToList())
        {
            if (p.FullName == printer.FullName)
            {
                p.NumberOfJobs = printer.NumberOfJobs;
                p.Status = printer.Status;
                return;
            }
        }
        Dispatcher.Invoke(() => _localPrinters.Add(printer));
    }
}

So far so good now comes the point I don't know how to handle. The ObservableCollection<Printer> is bound to a DataGrid were all general information is Displayed. Now if a user double clicks a Row, I want to show some 'deeper' information in a userControl. But I can't find a way to access the PrintQueue here because it's the wrong Thread.

到目前为止,现在非常好,我不知道如何处理。 ObservableCollection 绑定到DataGrid,显示所有常规信息。现在,如果用户双击一行,我想在userControl中显示一些“更深层”的信息。但是我找不到在这里访问PrintQueue的方法,因为它是错误的Thread。

private void Row_DoubleClick(object sender, MouseButtonEventArgs e)
{
    // Printer is fine, just the PrintQueue inside is full of System.InvalidOperationException
    Printer p = (sender as DataGridRow)?.DataContext as Printer;
    UcPrinterDetails.InitializeDetails(p.PrintQueue);

    UcPrinterDetails.Visibility = UcPrinterDetails.Visibility != Visibility.Visible ? Visibility.Visible : Visibility.Collapsed;
}

So my question here: What is the best way to access the PrintQueue object and which Thread is the owner of the object?

所以我的问题是:访问PrintQueue对象的最佳方法是什么,以及哪个Thread是对象的所有者?

1 个解决方案

#1


0  

You shouldn't use object (related to Windows functionality) in different thread then it was created in. In the Row_DoubleClick function just call one more time GetPrintQueues method and find the one that you interested in.

您不应该在不同的线程中使用对象(与Windows功能相关),然后创建它。在Row_DoubleClick函数中,只需再调用一次GetPrintQueues方法并找到您感兴趣的方法。

#1


0  

You shouldn't use object (related to Windows functionality) in different thread then it was created in. In the Row_DoubleClick function just call one more time GetPrintQueues method and find the one that you interested in.

您不应该在不同的线程中使用对象(与Windows功能相关),然后创建它。在Row_DoubleClick函数中,只需再调用一次GetPrintQueues方法并找到您感兴趣的方法。