我正在尝试绑定BindingList< myobject>这是在工作线程上操作到dataGridView.DataSource。这是我正在尝试做的一个例子。我甚至不确定我尝试做的事情是否正确。我不知道我在这做什么。我得到一个跨线程异常,我(半理解)为什么。我欢迎所有建议和更正。如果有人能指出我正确的方向/设计模式,以便有效和正确地做到这一点,我将不胜感激。 提前致谢, -DA
I'm trying to bind a BindingList<myobject> that's manipulated on a worker thread to a dataGridView.DataSource. Here's an example of what I'm trying to do. I'm not even sure if what I'm "trying" do is the correct way to go about this. I have no idea of what I'm doing here. I'm getting a cross thread exception and I (semi-understand) why. I welcome ALL suggestions and corrections. Would appreciate if someone would point me in the right direction/design pattern to implement in order to do this efficiently and correctly. Thanks in advance, -DA
public class Stock : INotifyPropertyChanged { private string symbol; private double price; private int size; public event PropertyChangedEventHandler PropertyChanged; public Stock(string symbol, double price, int size) { this.symbol = symbol; this.price = price; this.size = size; } public string Symbol { get { return symbol; } } public double Price { get { return price; } set { if (price != value) { price = value; OnPropertyChanged("Price"); } } } public int Size { get { return size; } set { if (size != value) { size = value; OnPropertyChanged("Size"); } } } private void OnPropertyChanged(string propertyName) { if(PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } }
public class StocksManager { // Members int NUM_PROCESSORS = Environment.ProcessorCount; MktDataSim mktData; List<Thread> workers; EventWaitHandle signal; Queue<Stock> workQueue; object sync; BindingList<Stock> stocksCollec; // Constructor public StocksManager() { mktData = new MktDataSim(); workers = new List<Thread>(); signal = new AutoResetEvent(false); workQueue = new Queue<Stock>(); sync = new object(); stocksCollec = new BindingList<Stock>(); mktData.StockUpdateHandler += new StockUpdateEventHandler (mktData_StockUpdateHandler); for (int i = 0; i < NUM_PROCESSORS; i++) { workers.Add(new Thread(worker)); workers[i].IsBackground = true; workers[i].Start(); } } // Properties public BindingList<Stock> StockCollection { get { return stocksCollec; } } // Methods/Event Handlers private void mktData_StockUpdateHandler(string symbol, double price, int size) { getMktData(new Stock(symbol, price, size)); } private void getMktData(Stock stock) { lock (sync) workQueue.Enqueue(stock); signal.Set(); } private void worker() { while (true) { Stock stock = null; lock (sync) { if (workQueue.Count > 0) stock = workQueue.Dequeue(); } if (stock != null) { string sym = stock.Symbol; double prc = stock.Price; int sz = stock.Size; // I'm TRYING to only add new stocks // but this isn't working because I // can't distinguish by symbol if (!stocksCollec.Contains(stock)) { stocksCollec.Add(new Stock(sym,prc,sz)); } else { int elmnt = stocksCollec.IndexOf(stock); stocksCollec[elmnt].Price = prc; stocksCollec[elmnt].Size = sz; } } else { signal.WaitOne(); } } } }
// GUI
// GUI
public partial class Form1 : Form { StocksManager stkMngr; BindingSource stocksDataSource; public Form1() { InitializeComponent(); stkMngr = new StocksManager(); // I'm using a bindingSource because // I'll need to be able to manipulate // my list of objects i.e. (sorting, removing, // updating, and deleting) stocksDataSource = new BindingSource(); stocksDataSource.DataSource = stkMngr.StockCollection; dgvDisplay.DataSource = stocksDataSource; }推荐答案
如果控件是由另一个 thread。一般 UI控件(如Label,Button等)都是在主线程上创建的。每当您尝试从工作线程访问UI控件时,您将获得跨线程异常。这就是你获得跨线程异常的原因。 你可以使用 BackgroundWorker 类用于在.Net中执行长时间运行的操作。以下链接可能有助于您了解BackgroundWorker类 msdn.microsoft/en-us/library/cc221403(v=vs.95).aspx [ ^ ] 如果您需要进一步的帮助请告诉我。 We cannot perform operation on a control, if that control was created by another thread. Generally UI Controls like Label, Button, etc. are created on Main Thread. Whenever you try to access UI control from worker thread you will get cross thread exception. This is the reason you are getting cross thread exception. You can use BackgroundWorker class for performing long running operation in .Net. Following link might help you to understand BackgroundWorker class msdn.microsoft/en-us/library/cc221403(v=vs.95).aspx[^] If you need further help please let me know.
嗨David, 不知道这是否仍然适用,但我是现在为货币创建一个类似的应用程序。 我不知道什么是最佳方法。 然而,我遇到了与你自己类似的问题,并为自己找到了解决方案。 我在下面的链接中解释了我的所作所为。使用ThreadedBindingList,它继承自BindingList。我还解释了我为解决我的跨线程异常问题所做的工作,将SyncronizationContext从UI传递到ThreadedBindingList,当时我将它分配给数据源到我的DataGridView。 stackoverflow/questions/30425283/binding-source-not-reflecting-new-removed-row-when-list-datasource-adds-removes/30446089#30446089 $ / b $ b 原始ThreadedBingingList(我发现)由Marc Gravell在此链接上提供。 groups.google/forum/# !msg / microsoft.public.dotnet.languages.csharp / IU5ViEsW9Nk / Bn9WgFk8KvEJ 希望如果你仍然有帮助需要它。 Hi David, Don't know if this still applies, but I'm creating a similar type of application, right now for Currencies. I don't know what would be the optimal approach either. However, I hit upon a similar issues as yourself, and found a solution for myself. I explain what I did in the link below. Employing a ThreadedBindingList, which inherits from BindingList. I also explain what I did to resolve my Cross-thread Exception issue, by passing the SyncronizationContext from the UI to the ThreadedBindingList at the time that I assigned it to the datasource to my DataGridView. stackoverflow/questions/30425283/binding-source-not-reflecting-new-removed-row-when-list-datasource-adds-removes/30446089#30446089 The Original ThreadedBingingList (that I found) was given by Marc Gravell on this link. groups.google/forum/#!msg/microsoft.public.dotnet.languages.csharp/IU5ViEsW9Nk/Bn9WgFk8KvEJ Hope this helps if you still need it.
更多推荐
如何将工作线程上的BindingList绑定到GUI线程C#WinForm上的BindingSource
发布评论