gpt4 book ai didi

c# - 在线程之间传递 List

转载 作者:太空宇宙 更新时间:2023-11-03 14:10:31 24 4
gpt4 key购买 nike

我有一个 List<Polyline>我需要在第二个线程中生成,以免失去 GUI 响应能力。线程完成后,我需要访问 List<Polyline>在 GUI 线程中显示。这是我遇到问题的地方。我正在使用匿名方法调用 UI 线程上的复制逻辑,将多段线复制到 List<Polyline> 中已经在 UI 线程上初始化。我收到“调用线程无法访问此对象,因为另一个线程拥有它。”

我已尝试使用 Clone 和 DeepCopy 扩展方法从线程列表复制到 UI 列表,但 Polyline 不可序列化。

    Class ThreadedExecuter<T> where T : class
{
public delegate void CallBackDelegate(T returnValue);
public delegate T MethodDelegate();
private CallBackDelegate callback;
private MethodDelegate method;

private Thread t;

public ThreadedExecuter(MethodDelegate method, CallBackDelegate callback)
{
this.method = method;
this.callback = callback;
t = new Thread(this.Process);
//XPSDocument requires STA
t.SetApartmentState(ApartmentState.STA);
}
public void Start()
{
t.Start();
}
private void Process()
{
T stuffReturned = method();
callback(stuffReturned);
}
}



void StartXPStoPolyThread()
{
ThreadedExecuter<List<Polyline>> executer = new ThreadedExecuter<List<Polyline>>(GeneratePolyFromXPS, PolyFromXPSComplete);
executer.Start();
}

List<Polyline> GeneratePolyFromXPS()
{

string file = @"C:\Users\Company\Desktop\shapes6.xps";
Company.XPStoPolyline.XPStoPolylineHelper myXPSPoly = new Company.XPStoPolyline.XPStoPolylineHelper(); //init brushes
List<Polyline> LocalList = myXPSPoly.ReadFileOutputPolylineList(file, CurrentConfig.ImportTolerance);


return LocalList;
}

void PolyFromXPSComplete(List<Polyline> PolylistIn)
{

this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background, new Action(() =>
{

PolylineList.Clear(); //already initialized in UI thread
PolylineList = new List<Polyline>(PolylistIn.Capacity);

foreach (Polyline currentPolyline in PolylistIn)
{
Polyline correctedPolyLine = new Polyline();
PointCollection myPointCollection = new PointCollection();
Point pointToAdd = currentPolyline.Points[0]; //"The calling thread cannot access this object because a different thread owns it."
myPointCollection.Add(pointToAdd);
for (int i = 1; i < currentPolyline.Points.Count; i++)
{
....copy points
}

correctedPolyLine.Points = myPointCollection;
correctedPolyLine.Stroke = currentPolyline.Stroke;
correctedPolyLine.StrokeThickness = 1;
PolylineList.Add(correctedPolyLine);
}

//display for testing
VectorGridCanvas.Children.Clear();
foreach (Polyline myPolyLine in PolylineList)
{
VectorGridCanvas.Children.Add(myPolyLine);
}

}));
}

最佳答案

因为 Polyline 是一个 WPF UIElement 类,所以它绑定(bind)到 UI 线程。如果您尝试从另一个线程访问它的任何属性,它将抛出异常。

请注意,Polyline 是一种显示类,而不是一种数据类型。您不应该摆弄 WPF 控件或来自后台线程的其他显示元素。 WPF 将在每一步都与您抗衡。

最好的办法是使用您自己设计的中间数据类型执行 XPS 到折线的转换计算。除了 UIElement 之外的任何东西都可以。值类型结构可能是合适的。一旦你完成了任何密集的计算体操保证后台线程,吐出你的数据并向 UI 线程发出数据可以发送的信号。然后,UI 线程可以读取中间数据并根据需要在 UI 线程上 构造多段线。

如果您要构建数千万条折线并观察到令人反感的 UI 问题,您可以将工作分成更小的批处理,以免一次阻塞 UI 的时间过长。

折线(和一般的 WPF)绑定(bind)到 UI 线程,再多的后台线程也无法改变这一点。

不要以为线程会拯救你。

首先,您是否确实存在明显的 UI 阻塞问题?如果没有,你就完成了。无需线程。

如果您确实遇到 UI 阻塞问题,是否可以将其分解为更小的批处理并仍然在 UI 线程上执行?如果是,你就完成了。无需线程。

如果使用后台线程确实是解决问题的最有效方法,那么在不使用 WPF 类(如 Polyline)的情况下实现它。

关于c# - 在线程之间传递 List<Polyline>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8017420/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com