Тупиковая проблема - PullRequest
       7

Тупиковая проблема

0 голосов
/ 28 апреля 2010

Здравствуйте, у меня проблема тупика со следующим кодом. Это происходит, когда я вызываю функцию 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;
        }
    }
}

EDIT: «Использование System.Threading;» это было просто для какого-то отладчика, где мы немного уснули, просто я забыл его удалить.

Мы добавили «замок (корпус)», чтобы увидеть, может ли он исправить мертвый замок, он не делает. Также программа не работает с многопоточностью, так что это не проблема.

Я исправил ошибку до 1008 *

if (inPoly(x, y))
    points.Add(new Point(x, y));

Сообщение об ошибке

CLR не удалось перейти из контекста COM 0x1bb7b6b0 в COM контекст 0x1bb7b900 в течение 60 секунд. поток, которому принадлежит пункт назначения контекст / квартира скорее всего либо делать не качать ждать или обработка очень долго работа без прокачки винды Сообщения. Эта ситуация обычно имеет отрицательное влияние на производительность и может даже привести к тому, что приложение становится не отвечает или использование памяти накапливается постоянно с течением времени. к избежать этой проблемы, все одиноки Резьба в квартире (STA) следует использовать прокачку примитивов ожидания (например, CoWaitForMultipleHandles) и регулярно качать сообщения в течение длительного выполняющиеся операции.

Ответы [ 3 ]

4 голосов
/ 28 апреля 2010

Это предупреждение Managed Debugging Assistant, касающееся использования COM-серверов в потоке. Одной из особенностей COM является то, что он автоматически обрабатывает многопоточность для компонентов, которые не поддерживают многопоточность. Он автоматически маршализирует вызов метода из фонового потока в поток пользовательского интерфейса, чтобы компонент не использовался небезопасным способом. Это полностью автоматически, вы сами не пишете код, чтобы это произошло.

Чтобы это работало правильно, поток пользовательского интерфейса должен быть свободен, чтобы он мог выполнить вызов метода. Предупреждение говорит о том, что поток пользовательского интерфейса не простаивал в течение минуты, что препятствует завершению вызова. Наиболее вероятная причина этого заключается в том, что поток пользовательского интерфейса блокируется, ожидая завершения потока. Этого никогда не произойдет, оно зашло в тупик. Или он мог просто быть занят выполнением кода в течение этой минуты, никогда не занимаясь выполнением своих обычных обязанностей, прокачивая цикл сообщений. Неперекачка цикла сообщений препятствует завершению маршализованного вызова и отключает предупреждение.

Это должно быть легко видно, главное окно вашего приложения должно быть заморожено и отображать сообщение «Не отвечает» в строке заголовка. Когда вы используете Debug + Break All, Debug + Windows + Threads и переключаетесь на поток пользовательского интерфейса, а затем просматриваете стек вызовов, вы должны увидеть место, где поток пользовательского интерфейса заблокирован. Исправьте это, не заставляя поток пользовательского интерфейса ждать в потоке или избегая использования компонента COM в рабочем потоке. Если это совершенно неуместно (не должно быть), вы можете отключить предупреждение с помощью Debug + Exceptions.

Это техническое объяснение предупреждения. Скучным является то, что в RTM-версии Visual Studio 2005 была ошибка. Что-то не так с отладчиком, он имел тенденцию отключать MDA при одном шаге или проверке переменных. Это исправлено в пакете обновления 1, обязательно скачайте и установите его, если вы еще этого не сделали.

1 голос
/ 28 апреля 2010

в этой статье MSDN они объясняют, почему лучше определить переменную, используемую только в операторе блокировки. Ясно, что это позволяет избежать многих подобных проблем.

0 голосов
/ 28 апреля 2010

Вы блокируете экземпляр "hull" в getMap () и затем при вызове getRectangle (); вы пытаетесь перечислить через "корпус".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...