Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过列表<;多段线>;线程之间_C#_Multithreading_Generics - Fatal编程技术网

C# 通过列表<;多段线>;线程之间

C# 通过列表<;多段线>;线程之间,c#,multithreading,generics,C#,Multithreading,Generics,我有一个列表,我需要在第二个线程中生成该列表,以免失去GUI响应能力。线程完成后,我需要访问GUI线程中的列表,以便显示。这就是我遇到问题的地方。我使用匿名方法调用UI线程上的复制逻辑,将多段线复制到已经在UI线程上初始化的列表中。我得到“调用线程无法访问此对象,因为另一个线程拥有它。” 我尝试了克隆和DeepCopy扩展方法从线程列表复制到UI列表,但是Polyline是不可序列化的 Class ThreadedExecuter<T> where T : class

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

我尝试了克隆和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);
                }

        }));           
    }
Class线程执行器,其中T:Class
{
公共委托void CallBackDelegate(T returnValue);
公共委托T MethodDelegate();
私有回调委托回调;
私有方法委托方法;
私有线程t;
公共线程执行器(MethodDelegate方法,CallBackDelegate回调)
{
这个方法=方法;
this.callback=回调;
t=新线程(此.Process);
//XPSDocument需要STA
t、 SetApartmentState(ApartmentState.STA);
}
公开作废开始()
{
t、 Start();
}
私有无效进程()
{
T stuffReturned=method();
回调(返回);
}
}
void StartXPStoPolyThread()
{
ThreadedExecuter executer=新的ThreadedExecuter(GeneratePolicyFromXPs,PolyFromXPSComplete);
executer.Start();
}
列表GeneratePolyFromXPS()
{
字符串文件=@“C:\Users\Company\Desktop\shapes6.xps”;
Company.XPStoPolyline.XPStoPolylineHelper myXPSPoly=新Company.XPStoPolyline.XPStoPolylineHelper();//初始化笔刷
List LocalList=myXPSPoly.ReadFileOutputPolylineList(文件,CurrentConfig.ImportTolerance);
返回LocalList;
}
void PolyFromXPSComplete(列出多段列表)
{
this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background,新操作(()=>
{
PolylineList.Clear();//已在UI线程中初始化
多段列表=新列表(多段列表容量);
foreach(多段线currentPolyline in PolylistIn)
{
折线修正折线=新折线();
PointCollection myPointCollection=新建PointCollection();
Point pointToAdd=currentPolyline.Points[0];/“调用线程无法访问此对象,因为它属于另一个线程。”
myPointCollection.Add(pointToAdd);
对于(int i=1;i
因为Polyline是一个WPF UIElement类,所以它被绑定到UI线程。如果您试图从另一个线程访问它的任何属性,它将抛出异常

请注意,多段线是一个显示类,而不是数据类型。您不应该摆弄背景线程中的WPF控件或其他显示元素。WPF将与你战斗的每一步


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

如果您有数以千万计的多段线要构建并观察一个令人不快的UI问题,您可以将工作分成更小的批,以避免一次阻塞UI太长时间

多段线(通常是WPF)绑定到UI线程,任何后台线程都不会改变这一点

不要以为线程可以拯救你

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

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


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

“最好的办法是使用自己设计的中间数据类型执行XPS到Polyline的转换计算。”谢谢,这就成功了。我用简单的基础知识创建了自己的多段线类,并从那里开始练习,在主线程上重建WPF多段线。