본문 바로가기
반응형

전체 글97

error. 이벤트핸들러 이름 충돌 문제 원인은 이름 충돌이에요.당신이 만든 VIK.ImageGrabbedEventArgs (버퍼+카메라)와Basler SDK의 Basler.Pylon.ImageGrabbedEventArgs (GrabResult 포함)이 같은 이름이라, StreamGrabber.ImageGrabbed 구독 시 컴파일러가 잘못된 쪽을 참고하고 있어요. 그래서“EventHandler에 맞는 오버로드 없음”“DisposeGrabResultIfClone, GrabResult가 없음”같은 에러가 터집니다. (이 멤버들은 Basler 쪽에만 있어요.)빠른 해결: 형식 별칭 + 핸들러 이름 구분Basler 파일에서 형식 별칭을 추가하고, 이벤트 핸들러를 Basler 전용으로 분리하세요.1) using 별칭 추가 (파일 상단)using .. 2025. 9. 22.
volatile는 멀티스레드에서 “가벼운 동기화”를 위한 읽기/쓰기 가시성 보장 장치 volatile는 멀티스레드에서 “가벼운 동기화”를 위한 읽기/쓰기 가시성 보장 장치라고 이해하면 편합니다.private volatile bool _isGrabbing = false;처럼 플래그에 쓰면, 다른 스레드가 값 변경을 즉시 보고 잘 멈추거나 시작할 수 있게 해줘요.volatile가 뭔가요?효과: 해당 필드에 대한 **읽기(Read)**와 **쓰기(Write)**가**CPU/컴파일러 재정렬(reordering)**로 서로 엇갈리지 않게 만들고,코어별 캐시/레지스터에만 머물다 안 보이는(stale) 값이 되는 일을 막아,다른 스레드에서 최신 값을 즉시 관측할 수 있게 합니다.(쉽게 말해: “바로 보이게 하고, 읽기/쓰기 순서를 뒤바꾸지 말라”는 메모리 장벽을 넣어줍니다. 읽기는 acquire, 쓰.. 2025. 9. 19.
왜 IDisposable을 구현하나요? 핵심 한 줄 요약**IDisposable = “내가 잡고 있는 외부 자원(파일 핸들, GDI, 스레드/Task/Timer 등)을 사용이 끝나면 즉시, 확정적으로 해제할 수 있게 해주는 계약(패턴)”**입니다.GC는 메모리만 회수하지 OS 자원(파일·소켓·GDI·스레드 핸들 등)은 즉시 정리하지 못하므로, 이런 자원을 가진 타입은 반드시 IDisposable을 구현해야 해요.왜 IDisposable을 구현하나요?결정적(Deterministic) 해제using (...) { ... } 블록이 끝나는 즉시 Dispose()가 호출되어 OS 핸들/타이머/스레드/그래픽 자원 등을 반납합니다.GC는 언제 실행될지 몰라요(비결정적). 파일 잠금·GDI 핸들 같은 건 지연 해제되면 곧바로 문제가 납니다.리소스 누수/잠.. 2025. 9. 19.
“직접 델리게이트 콜백” → “.NET 표준 이벤트 패턴(Event + EventArgs)” 왜 바꿨나? (Delegate → Event + EventArgs)1) .NET 표준 이벤트 패턴에 맞춤.NET에서 이벤트는 관례적으로 event EventHandler 형태를 써요.이렇게 하면 구독/해제(+=, -=), 멀티캐스트(여러 핸들러 동시 호출), 외부에서 임의 호출 차단 같은 이벤트 전용 보호 장치가 자동으로 따라옵니다.반면, public OnImageGrabbedEventDelegate OnImageGrabbedCallback; 같은 일반 필드 델리게이트는외부에서 통째로 갈아끼우기가 가능(기존 구독이 날아갈 위험)외부 코드가 임의로 호출도 가능(캡슐화 약함)멀티 구독/해제 동작이 명확하지 않음2) 시그니처 표준화: object sender, TEventArgs e이벤트 핸들러는 통일된 모양.. 2025. 9. 19.
sealed를 왜 써야 할까? sealed는 **“상속 불가”**를 뜻해요.즉 public sealed class ImageGrabbedEventArgs : EventArgs 라면, 이 클래스를 다른 클래스가 상속(derive)할 수 없습니다.왜 쓰나요?설계 의도 고정: 이벤트 페이로드 형태를 바꾸지 않도록 방지(파생형으로 변형 금지).안전성: 파생 클래스가 동작을 바꾸어 역호환/버그를 유발하는 것을 차단.성능 이점: JIT가 가상 호출을 줄이고(inlining 등) 최적화할 여지가 생김.간단한 데이터 전달용(EventArgs 계열)은 보통 불변 + sealed로 두는 게 흔한 패턴.특징 요약sealed class → 상속 금지 (하지만 인터페이스 구현은 가능).sealed는 클래스에 붙이면 상속을 막고, 메서드에 붙이면 overri.. 2025. 9. 19.
C#의 readonly 키워드 1) readonly가 뭔가요?필드(멤버 변수)에 붙이는 한정자로,선언 시 또는 생성자(ctor) 안에서만 한 번 값을 할당할 수 있고, 그 이후에는 수정이 불가능합니다.즉, 객체가 만들어진 뒤에는 바뀌지 않아야 할 값에 사용합니다.(정확히 말하면 참조형의 경우 **참조(주소)**가 고정될 뿐, 참조 대상 내부 상태까지 자동으로 불변이 되는 것은 아닙니다.)2) 왜/언제 쓰나요? (써야 할 이유)불변성(immutability) 보장: 실수로 값이 바뀌는 버그를 차단합니다. 클래스 불변식을 지키기 쉬워요.코드 의도 표현: “이 값은 생성 시 결정되고 이후 변하지 않는다”를 컴파일러 수준에서 명시합니다.스레드 안정성에 기여: 공유되는 상태가 줄어들어 동시성 버그 위험을 줄입니다.설계 간결화: 의존성, 구성(.. 2025. 9. 19.
null-coalescing assignment 연산자(??=) 가 C# 8.0에서 추가된 문법이라, C# 7.3 컴파일러로는 사용할 수 없다는 뜻입니다. 좋은 포인트예요. 오류 메시지는 null-coalescing assignment 연산자(??=) 가 C# 8.0에서 추가된 문법이라, C# 7.3 컴파일러로는 사용할 수 없다는 뜻입니다.빠른 수정 (원인→해결)원인:assemblies ??= new[] { Assembly.GetExecutingAssembly() }; // C# 8.0 문법C# 7.3 호환 수정:if (assemblies == null) assemblies = new[] { Assembly.GetExecutingAssembly() };또한, 제가 드렸던 예시 중에 using var 도 C# 8.0 문법입니다. C# 7.3에서는 전통적인 using (...) { } 블록으로 바꿔주면 됩니다.드롭인 패치: C# 7.3 호환 버전 메서드들아래는.. 2025. 9. 11.
VisionThread/EmguVision 라이브·검사 공통 파이프라인 리팩토링 (풀코드) VisionThread/EmguVision 라이브·검사 공통 파이프라인 리팩토링 (풀코드)아래 코드는 그랩 콜백에서 포인터를 즉시 안전 복제(Mat.Clone) 하고, 라이브/검사 경로를 하나의 공통 파이프라인으로 통합한 구현입니다.포인터 수명 안전: 콜백 내 즉시 Mat.Clone()UI 스레드 규칙 준수: 화면 갱신은 BeginInvoke로 UI 스레드에서지연 최소화: 라이브는 “최신 1장만 유지” + 게이트로 중복 렌더 억제재사용성: SharedPipeline(...) 한 곳에서 라이브/검사 공통 처리 분기1) 클래스명VisionThread (그랩 콜백을 보유)EmguVision (화면 컨트롤)2) 클래스 개요 (Overview)VisionThread는 카메라 프레임 수신 시 그랩 포인터를 즉시 M.. 2025. 9. 10.
EmguImage 안에 IInputArray를 반환하는 getter 좋아요! EmguImage 안에 IInputArray를 반환하는 getter들을 아래처럼 추가하면 됩니다.전체 이미지 차용 참조(Dispose 금지)ROI 기반 소유 참조(Dispose 필요)(호환용) 예전 코드에서 쓰던 Image 프로퍼티도 함께 제공합니다.// EmguImage 클래스 내부에 추가하세요 (namespace/using 동일)/// /// (호환용) 현재 내부 Mat을 IInputArray로 노출합니다. /// - 차용 참조(borrowed)이며, 호출자가 Dispose 하면 안 됩니다./// - 내부 m_Mat의 수명에 종속됩니다./// public IInputArray Image{ get { EnsureNotDisposed(); return IsVo.. 2025. 9. 9.
private static bool IsFiniteFloat(float v) => !(float.IsNaN(v) || float.IsInfinity(v)); 아래 한 줄짜리 헬퍼의 의도/동작/사용 맥락을 정리해 드릴게요.private static bool IsFiniteFloat(float v) => !(float.IsNaN(v) || float.IsInfinity(v));1) 함수 개요 (Overview)역할: 입력한 float v가 유한한 수(finite) 인지 검사합니다.유한값 = NaN(숫자 아님)도 아니고, ±Infinity(무한대)도 아닌 모든 실수 값.왜 필요한가?.NET Framework 4.x에는 float.IsFinite(...)가 없어 동일 기능을 대체하기 위한 유틸입니다.확대 배율, 좌표 스케일 등 연산 결과를 화면에 쓰기 전에 값의 안정성을 보장하기 위해 사용합니다.2) 시그니처와 접근성private: 현재 클래스 내부에서만 사용.st.. 2025. 9. 9.
반응형