2010-04-28 7 views
0

안녕하세요 저는 다음 코드에 교착 상태 문제가 있습니다. 그것은 함수 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; 
     } 
    } 
} 

편집 : 은 "사용하여 System.Threading;" 우리가 thead를 약간 자게했던 약간의 디버깅 ealyer를 위해 단지 있었다, 나는 그것을 단지 삭제하는 것을 잊었다.

우리는 "자물쇠 (선체)"를 추가하여 죽은 자물쇠를 고칠 수 있는지 확인했습니다. 또한 프로그램이 멀티 스레딩과 함께 실행되지 않으므로 문제가되지 않습니다.

나는

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

의 CLR은 60 초 동안 COM 상황 0x1bb7b900에 COM 컨텍스트 0x1bb7b6b0에서 을 전환 할 수 없었다

오류 메시지를 accuring 오류로 내려 narroed 한 . 대상을 소유하는 스레드 컨텍스트/아파트는 펌핑 대기없이 수행하거나 매우 긴 실행 처리중인 Windows 메시지를 처리 ​​중일 수 있습니다. 이 상황은 일반적으로 에 부정적인 성능 영향을 미치며 은 응용 프로그램이 응답하지 않거나 시간이 지남에 따라 계속 누적되는 메모리 사용량이 이 될 수 있습니다. 피할이 문제에 대한 모든 단일 스레드 아파트 (STA)는 가 (예 : CoWaitForMultipleHandles로) 펌핑 대기 프리미티브를 사용해야하고 정기적으로 긴 실행 작업을 수행하는 동안 메시지 펌프 스레드.

+0

System.Threading을 참조하지만 사용중인 네임 스페이스에서 아무 것도 볼 수 없습니다. 다른 스레드를 돌리고 있습니까? 그렇다면 Polygon에서 어떤 메소드를 호출합니까? –

+0

이것은 실제로 (어떻게 든) 데이터베이스 교착 상태입니까? 올바른 오류 메시지를 게시하고 가능한 경우 스택 추적을 게시 할 수 있습니까? –

+0

이것은 COM interop 문제이므로 해당 태그를 질문에 추가했습니다. –

답변

4

스레드에서 COM 서버를 사용하는 것과 관련된 관리되는 디버깅 도우미 경고입니다. COM의 기능 중 하나는 멀티 스레딩을 지원하지 않는 구성 요소의 스레딩을 자동으로 처리한다는 것입니다. 백그라운드 스레드에서 UI 스레드로 메서드 호출을 자동으로 마샬링하여 스레드가 안전하지 않은 방식으로 구성 요소를 사용하지 않도록합니다. 이 작업은 완전히 자동으로 수행되므로 코드를 직접 작성하지 않아도됩니다.

제대로 작동하려면 UI 스레드가 메소드 호출을 실행할 수 있도록 유휴 상태 여야합니다. 이 경고는 UI 스레드가 이 아니며 1 분 동안 유휴 상태였던이 아니라면 호출이 완료되지 못하도록합니다. 가장 큰 이유는 UI 스레드가 차단되어 스레드가 완료 될 때까지 기다리는 것입니다. 그것은 결코 일어나지 않을 것입니다, 그것은 교착 상태입니다. 아니면 그 순간에 코드를 실행하는 데 바쁠 수 있었고 정상적인 업무를 수행하지 않고 메시지 루프를 펌핑 할 수있었습니다. 메시지 루프를 펌핑하지 않으면 마샬링 된 호출이 완료되고 경고가 이동되지 않습니다.

이것은 쉽게 볼 수 있어야합니다. 앱의 기본 창이 고정되어 있어야하며 제목 표시 줄에 "응답 없음"메시지가 표시되어야합니다.Debug + Break All, Debug + Windows + Threads를 사용하고 UI 스레드로 전환 한 다음 호출 스택을 보면 UI 스레드가 교착 상태에있는 곳을 볼 수 있습니다. 스레드에서 UI 스레드를 대기시키지 않거나 작업자 스레드에서 COM 구성 요소를 사용하지 않는 방법으로 문제를 해결하십시오. 완전히 부적절한 경우 (그렇게해서는 안 됨) 디버그 + 예외로 경고를 끌 수 있습니다.

경고에 대한 기술적 설명입니다. 지루한 것은 Visual Studio 2005의 RTM 버전에 버그가 있다는 것입니다. 디버거에 문제가있어 단일 스테핑 또는 변수 검사 중에 MDA를 이동하는 경향이있었습니다. 서비스 팩 1에서이 문제가 해결되었으므로 아직 수행하지 않았다면 다운로드하여 설치하십시오.

+0

알고리즘을 자체 스레드에서 실행하여 문제를 해결했습니다. – Androme

0

getMap()에서 "hull"인스턴스를 잠그고 있고 getRectangle()을 호출하면 잠금이 해제됩니다. 당신은 "선체"를 통해 열거하려고 시도하고 있습니다.

+1

하지만 getRectangle()이 동일한 스레드에서 호출되어 잠금이 단순 목록의 열거를 차단하지 않을까요? –

+0

동일한 스레드에서 잠긴 List <>에 대한 반복은 아무런 문제가되지 않습니다. –

1

이 msdn article에있는 이유는 lock 문에서만 사용되는 변수를 정의하는 것이 더 나은 이유입니다. 분명히 그런 종류의 문제를 피할 수 있습니다.