C# 死锁问题

C# 死锁问题,c#,com-interop,deadlock,C#,Com Interop,Deadlock,您好,下面的代码有死锁问题。调用函数getMap()时会发生这种情况。但我真的看不出是什么原因造成的 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Drawing.Imaging; using System.Threading; using AForge; using AForge.Imaging;

您好,下面的代码有死锁问题。调用函数getMap()时会发生这种情况。但我真的看不出是什么原因造成的

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Threading;

using AForge;
using AForge.Imaging;
using AForge.Imaging.Filters;
using AForge.Imaging.Textures;
using AForge.Math.Geometry;

namespace CDIO.Library
{
    public class Polygon
    {
        List<IntPoint> hull;
        public Polygon(List<IntPoint> hull)
        {
            this.hull = hull;
        }

        public bool inPoly(int x, int y)
        {
            int i, j = hull.Count - 1;
            bool oddNodes = false;

            for (i = 0; i < hull.Count; i++)
            {
                if (hull[i].Y < y && hull[j].Y >= y
                || hull[j].Y < y && hull[i].Y >= y)
                {
                    try
                    {
                        if (hull[i].X + (y - hull[i].X) / (hull[j].X - hull[i].X) * (hull[j].X - hull[i].X) < x)
                        {
                            oddNodes = !oddNodes;
                        }
                    }
                    catch (DivideByZeroException e)
                    {
                        if (0 < x)
                        {
                            oddNodes = !oddNodes;
                        }
                    }
                }
                j = i;
            }
            return oddNodes;
        }

        public Rectangle getRectangle()
        {
            int x = -1, y = -1, width = -1, height = -1;
            foreach (IntPoint item in hull)
            {
                if (item.X < x || x == -1)
                    x = item.X;
                if (item.Y < y || y == -1)
                    y = item.Y;


                if (item.X > width || width == -1)
                    width = item.X;
                if (item.Y > height || height == -1)
                    height = item.Y;


            }
            return new Rectangle(x, y, width-x, height-y);
        }

        public Point[] getMap()
        {
            List<Point> points = new List<Point>();
            lock (hull)
            {
                Rectangle rect = getRectangle();
                for (int x = rect.X; x <= rect.X + rect.Width; x++)
                {
                    for (int y = rect.Y; y <= rect.Y + rect.Height; y++)
                    {
                        if (inPoly(x, y))
                            points.Add(new Point(x, y));
                    }
                }
            }
            return points.ToArray();
        }

        public float calculateArea()
        {
            List<IntPoint> list = new List<IntPoint>();
            list.AddRange(hull);
            list.Add(hull[0]);

            float area = 0.0f;
            for (int i = 0; i < hull.Count; i++)
            {
                area += list[i].X * list[i + 1].Y - list[i].Y * list[i + 1].X;
            }
            area = area / 2;
            if (area < 0)
                area = area * -1;
            return area;
        }
    }
}
错误消息

CLR无法转换 从COM上下文0x1bb7b6b0到COM 上下文0x1bb7b900持续60秒。这个 拥有目标的线程 上下文/公寓是最有可能的 进行非泵送等待或 处理一个非常长的运行时间 无泵送窗操作 信息。这种情况普遍存在 对绩效产生负面影响,并可能 甚至导致应用程序变得 无响应或内存使用 随着时间的推移不断积累。到 避免这个问题,所有的单 螺纹单元(STA)螺纹 应该使用泵送等待原语 (如CoWaitForMultipleHandles)和 在长时间内定期发送消息 运行操作


在getMap()中锁定实例“hull”,然后调用getRectangle();您正试图通过“外壳”枚举

在getMap()中锁定实例“hull”,然后调用getRectangle();您正试图通过“外壳”枚举

在本msdn中,他们解释了为什么最好只在lock语句中定义一个变量。显然,它避免了许多此类问题。

在本msdn中,他们解释了为什么最好只在lock语句中定义一个变量。显然,它避免了许多此类问题。

这是一个托管调试助手警告,与在线程上使用COM服务器有关。COM的一个特性是,它自动处理不支持多线程的组件的线程。它会自动将方法调用从后台线程封送到UI线程,这样组件就不会以线程不安全的方式使用。这是完全自动的,您不需要自己编写任何代码来实现这一点

要使其正常工作,UI线程必须处于空闲状态,以便可以执行方法调用。警告告诉您UI线程有一分钟没有空闲,它会阻止调用完成。最可能的原因是UI线程正在阻塞,等待线程完成。这种情况永远不会发生,它已经陷入僵局。或者,它可能只是在那一分钟忙于运行代码,从来没有抽出时间来完成它的正常任务,不断循环消息。不泵送消息循环会阻止封送调用完成并触发警告

这应该是显而易见的,你的应用程序的主窗口应该被冻结,并在标题栏中显示“未响应”消息。当您使用Debug+breakall、Debug+Windows+Threads并切换到UI线程,然后查看调用堆栈时,您应该会看到UI线程死锁的位置。通过不让UI线程等待线程或避免在工作线程上使用COM组件来修复它。如果它完全不合适(不应该),那么您可以关闭带有调试+异常的警告


这是对警告的技术解释。令人厌烦的是,VisualStudio2005的RTM版本中有一个bug。调试器出了问题,在单步执行或检查变量时,它倾向于使MDA跳闸。这在Service Pack 1中得到了修复,如果您尚未完成此操作,请确保下载并安装它。

这是一个托管调试助手警告,与在线程上使用COM服务器有关。COM的一个特性是,它自动处理不支持多线程的组件的线程。它会自动将方法调用从后台线程封送到UI线程,这样组件就不会以线程不安全的方式使用。这是完全自动的,您不需要自己编写任何代码来实现这一点

要使其正常工作,UI线程必须处于空闲状态,以便可以执行方法调用。警告告诉您UI线程有一分钟没有空闲,它会阻止调用完成。最可能的原因是UI线程正在阻塞,等待线程完成。这种情况永远不会发生,它已经陷入僵局。或者,它可能只是在那一分钟忙于运行代码,从来没有抽出时间来完成它的正常任务,不断循环消息。不泵送消息循环会阻止封送调用完成并触发警告

这应该是显而易见的,你的应用程序的主窗口应该被冻结,并在标题栏中显示“未响应”消息。当您使用Debug+breakall、Debug+Windows+Threads并切换到UI线程,然后查看调用堆栈时,您应该会看到UI线程死锁的位置。通过不让UI线程等待线程或避免在工作线程上使用COM组件来修复它。如果它完全不合适(不应该),那么您可以关闭带有调试+异常的警告


这是对警告的技术解释。令人厌烦的是,VisualStudio2005的RTM版本中有一个bug。调试器出了问题,在单步执行或检查变量时,它倾向于使MDA跳闸。这在Service Pack 1中得到了修复,如果您还没有这样做,请务必下载并安装它。

但是getRectangle()正在同一线程上被调用,因此锁不会阻止简单列表的枚举,是吗?在同一线程中迭代锁定的列表没有任何问题。但是getRectangle()是在同一线程上调用的,因此锁不会阻止简单列表的枚举,对吗?在同一线程中迭代锁定列表没有任何问题。您引用System.Threading,但我看不到使用该命名空间的任何内容。你在别的地方纺线吗?如果是这样,他们对多边形调用了什么方法?这实际上(不知何故)是一个数据库死锁吗?你能用pos吗
if (inPoly(x, y))
    points.Add(new Point(x, y));