首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >死锁问题

死锁问题
EN

Stack Overflow用户
提问于 2010-04-28 08:51:01
回答 3查看 538关注 0票数 0

你好,下面的代码出现了死锁问题。当我调用函数getMap()时会发生这种情况。但我不知道是什么导致了这一切。

代码语言:javascript
复制
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;
        }
    }
}

编辑:“使用System.Threading;”只是为了一些调试解析器,我们使头睡觉,我只是忘了删除它。

我们增加了“锁(船体)”,看看它是否能修复死锁,它不会。此外,程序没有运行与多线程,所以这不是问题。

我已经把它归结为错误

代码语言:javascript
复制
if (inPoly(x, y))
    points.Add(new Point(x, y));

错误信息

CLR无法从COM上下文0x1bb7b6b0转换到COM上下文0x1bb7b900 60秒。拥有目标上下文/单元的线程很可能要么执行非抽水等待,要么处理非常长时间运行的操作而不发送Windows消息。这种情况通常会对性能产生负面影响,甚至可能导致应用程序变得无响应或内存使用量随着时间的推移而不断累积。为了避免这个问题,所有单线程单元(STA)线程都应该使用泵送等待原语(如CoWaitForMultipleHandles),并在长时间运行操作期间常规地对消息进行泵入。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-04-28 11:44:23

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

为了使其正常工作,UI线程必须处于空闲状态,以便它能够执行方法调用。警告告诉您UI线程没有空闲一分钟,它阻止了调用的完成。最可能的原因是UI线程阻塞,等待线程完成。这是永远不会发生的,它已经陷入僵局。或者,它可能只是忙着运行代码一分钟,从来没有时间去做它的正常职责,抽水消息循环。如果不对消息循环进行抽吸,将阻止封送处理调用完成并触发警告。

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

这是警告的技术解释。令人厌烦的是,Visual 2005的RTM版本中有一个bug。调试器有问题,在单步执行或检查变量时,它往往会绊倒MDA。它在Service 1中被修复了,如果你还没有这样做的话,一定要下载并安装它。

票数 4
EN

Stack Overflow用户

发布于 2010-04-28 09:03:03

在这个msdn 文章中,他们解释了为什么只在lock语句中定义一个变量更好。显然,它避免了许多这样的问题。

票数 1
EN

Stack Overflow用户

发布于 2010-04-28 08:54:47

您正在锁定getMap()中的实例"hull“,然后在调用getRectangle()时,尝试通过"hull”枚举。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2727967

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档