2012-04-14 5 views
2

DevExpress GridControl이 BindingList에 바인딩되어 있습니다.스레드에서 생성 된 객체의 수명에 대한 설명이 필요합니다.

이 문제는 직접 XtraGrid와 연결되지 않은 : 나는 그것을 봤 다음과 같은 설명을 발견,

나는 스레드에서는 바인딩을 수정하기 위해 노력하고이 예외가 발생했습니다. 안타깝게도 동기화에 많은 문제를 야기하기 때문에 백그라운드 스레드에서 그리드의 데이터 소스를 변경할 수 없습니다. XtraGrid는 백그라운드 스레드가 변경하는 것과 동시에 기본 데이터 소스에서 일부 작업을 수행 할 수 있습니다. 이 경우 그리드는 나중에 변경 알림을 수신하고 위에서 언급 한 문제를 일으킬 수있는 행을 데이터 소스에서 업데이트하려고합니다. 이 문제는 많은 경우에 발생할 수 있습니다. 예를 들어 사용자가 데이터를 편집 할 때 데이터를 그룹화하거나 XtraGrid가 요약을 다시 계산하려고합니다. 이 문제를 해결할 수있는 유일한 방법은 백그라운드 스레드 내에서 Grid의 DataSource 참조를 변경하는 것입니다 (참고 : Invoke 메서드를 사용하여 구현해야합니다). 다르게 말하자면, 백그라운드 스레드 내에서 DataSource의 로컬 복사본으로 작업하고 필요한 경우 해당 클론을 Grid의 DataSource에 전달해야합니다. 첨부 된 예제에서이 접근법을 보여주는 샘플 프로젝트를 찾을 수 있습니다.

내가 노력

는이 결과, 말씀 :

proxyWorker = new Thread(() => 
{ 
    //Clone the datasource into the thread 
    BindingList<Proxy> newList = new BindingList<Proxy>(proxies); 

    //Set the proxy source to the cloned datasource in the thread 
    gcProxies.BeginInvoke(new MethodInvoker(delegate { gcProxies.DataSource = newList; })); 

    //Logic here 
}); 

proxyWorker.Name = "proxyTester"; 

proxyWorker.Start(); 

그것은 작동하지만, 내가 이해하지 못하는 것은 스레드 종료 후 데이터 소스에 무슨 일입니까? newList가 파괴되지 않았습니까?

내가 생각하는 말에 나는 newList 재 클론 것이며

new list 삶에 C#을 가비지 컬렉션 '하나 하나'의

+1

질문을 요약하는 제목을 입력하십시오. –

+0

고침, 미안하다. 제대로 설정하는 것을 잊어 버렸다. – TheGateKeeper

답변

3

당신의 혼란은 .NET 객체가 그것을 만든 스레드와 연결되어 있다고 생각한다는 사실에서 비롯된 것 같습니다. 그렇지 않은 경우 프로세스의 모든 스레드가 동일한 GC 힙을 공유합니다. 목록 <> 하나의 스레드에서 생성 된 객체는 다른 객체에서 List <>과 다르지 않습니다. 어떤 식 으로든 객체를 생성 한 스레드를 유지하지는 않습니다.

인 경우 스레딩 문제는 스레드로부터 안전하지 않은 많은 클래스가 있다는 것입니다.이것은 모든 UI 구성 요소의 경우입니다. 여러분이 이 할 수없는 것은 do가 다른 스레드로부터 그러한 클래스 객체의 속성을 할당하는 반면 그 속성 값은 UI 스레드에서도 사용될 수 있습니다. UI 구성 요소의 거의 모든 속성에는 이러한 제한이 있습니다. 속성 할당이 직접 보이지 않기 때문에 데이터 바인딩은 특히 까다 롭습니다. 바인딩이 설정하는 다른 모든 속성이 아닌 DataSource 만 설정합니다. Control.BeginInvoke 또는 Dispatcher.BeginInvoke를 사용하면 속성 값이 컨트롤을 만든 동일한 스레드에 설정되므로 스레드 안전 문제가 해결됩니다.

+0

내가 마지막으로 수행 한 작업은 바인딩 된 객체를 스레드로 복제하는 것이었고, 최종 복제시 원래의 소스로 되돌려 보냈습니다. 위대한 작품! – TheGateKeeper

2

이다 proxies (원본 소스)로 다시 설정한다는 것입니다 gcProxies.DataSource을 통해 참조하십시오.

해당 목록에 대한 참조가 부족할 때까지 당신은 훌륭합니다.

'목록'과 관련하여 특정 '크로스 스레드'문제가없는 한 크로스 스레드에 액세스하거나 다른 스레드에서 액세스하거나 다른 스레드에서 액세스하는 경우 - 모두 잘 작동합니다.
여기에서는 초기화 만하고 DataSource를 통해 다시 사용하지 않으므로 모두 정상입니다.

희망이

편집하는 데 도움이 : 코멘트에 답변을, 내가 조금 당신이 부수적으로, 객체의 '라이프 사이클'과 아무 상관이 당신의 객체를 생성

스레드를 단순화 해요을 - 스레드는 객체를 소유하지 않습니다. 응용 프로그램 도메인은 범위를 벗어 났지만 스레드 경계를 '교차'하거나 원하는대로 수행 할 수 있지만 코드/객체를 동기화해야합니다.

+0

프로그램의 다른 부분에서 다시 사용하고 오류가 발생합니다. 마지막에 원래 위치에 복제 된 데이터 소스를 다시 복사해야합니까? – TheGateKeeper

+0

@TheGateKeeper - 귀하의 질문은 참조 및 참조 유형에 관한 것으로 밝혀졌습니다. –

+0

끝에 @TheGateKeeper? 아니요, 당신은 당신의 문제를 적절히 다루어야 만합니다. Henk이 말했듯이 오류에 대한 더 많은 데이터를 추가해야합니다. 오류가 발생한 곳, 액세스하는 곳 등. 기본적으로 동기화가 필요합니다. 다른 장소에서 사용되는 경우 'Invoke'가 가능합니다 (가능한 경우 항상 간단하지는 않음) – NSGaga