当我在选择了视图的情况下向DataTable插入一行时,似乎我的应用程序崩溃了。据推测,这与一些交叉线程问题有关,但我并不完全确定如何解决它。这是我对DataTable的定义:
public class Logging
{
public DataTable Logs;
public Logging()
{
Logs = new DataTable();
Logs.Columns.Add("Level", typeof(int));
Logs.Columns.Add("Message", typeof(string));
}
public void LogMessage(int level, string message)
{
DataRow row = Logs.NewRow();
row["Level"] = level;
row["Message"] = message;
Logs.Rows.Add(row);
}
}
这会按照我的预期生成DataTable,并且工作正常。然后我将它绑定到WPF ListView控件,如下所示:
<ListView x:Name="lvConsole">
<ListView.View>
<GridView>
<GridViewColumn Header="Level" Width="50" DisplayMemberBinding="{Binding Path=Level}"/>
<GridViewColumn Header="Message" Width="376" DisplayMemberBinding="{Binding Path=Message}"/>
</GridView>
</ListView.View>
</ListView>
还可以将其添加到C#:
中lvConsole.ItemsSource = Util.Logger.Logs.DefaultView;
因此,为了产生问题,我只需打开包含列表视图的表单,单击它并滚动一点,我收到以下错误:
An unhandled exception of type 'System.InvalidOperationException' occurred in PresentationFramework.dll
Additional information: An ItemsControl is inconsistent with its items source.
查看更多细节,看来这是潜在的问题:
{"Information for developers (use Text Visualizer to read this):\r\nThis exception was thrown because the generator for control 'System.Windows.Controls.ListView Items.Count:20' with name 'lvConsole' has received sequence of CollectionChanged events that do not agree with the current state of the Items collection. The following differences were detected:\r\n Accumulated count 12 is different from actual count 20. [Accumulated count is (Count at last Reset + #Adds - #Removes since last Reset).]\r\n\r\nOne or more of the following sources may have raised the wrong events:\r\n System.Windows.Controls.ItemContainerGenerator\r\n System.Windows.Controls.ItemCollection\r\n System.Windows.Data.BindingListCollectionView\r\n System.Data.DataView\r\n(The starred sources are considered more likely to be the cause of the problem.)\r\n\r\nThe most common causes are (a) changing the collection or its Count without raising a corresponding event, and (b) raising an event with an incorrect index or item parameter.\r\n\r\nThe exception's stack trace describes how the inconsistencies were detected, not how they occurred. To get a more timely exception, set the attached property 'PresentationTraceSources.TraceLevel' on the generator to value 'High' and rerun the scenario. One way to do this is to run a command similar to the following:\n System.Diagnostics.PresentationTraceSources.SetTraceLevel(myItemsControl.ItemContainerGenerator, System.Diagnostics.PresentationTraceLevel.High)\r\nfrom the Immediate window. This causes the detection logic to run after every CollectionChanged event, so it will slow down the application.\r\n"}
有谁知道我需要做些什么来解决这个问题?我尝试了很多东西,其中之一就是:
private static object _syncLock = new object();
BindingOperations.EnableCollectionSynchronization(Logs.Rows, _syncLock);
这似乎没有做任何有用的事情,也许它与我一次从两个线程调用LogMessage有关?
答案 0 :(得分:0)
我很确定我找到了一个好的解决方法,但不确定它会持续多长时间。我会分享它,不管希望它是对的......
private void logMessage(object parameters)
{
object[] Paras = (object[])parameters;
int level = Convert.ToInt32(Paras[0]);
string message = (string)(Paras[1]);
DataRow row = Logs.NewRow();
row["Level"] = level;
row["Message"] = message;
Logs.Rows.Add(row);
}
public void LogMessage(int level, string message)
{
object lvl = Convert.ToString(level);
object msg = message;
object[] ob = { lvl, msg };
if (Util.client.player.isRunning)
{
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new ParameterizedThreadStart(logMessage), ob);
ParameterizedThreadStart pts = new ParameterizedThreadStart(logMessage);
}
}
我必须创建一个新方法,它使用应用程序调度程序来调用编辑列表的方法,如果我更正,将从应用程序主线程编辑列表(巧合的是,不是写入列表的那个,而是那个不断显示它的那个。)
这一切都相当混乱,如果其他人能想出更好的解释方法,请继续:)