2011-08-07 8 views
0

양식이 있고 제어 할 수 없습니다. 데이터베이스에서 컨트롤을 가져 와서 프로젝트가 느려서 스레딩을 사용할 수 있다고 생각하지만 오류가 발생합니다.다중 스레드 오류

void Form_Load(object sender,EventArgs e) 
    { 

    SqlDataAdapter adap=new SqlDataAdapter("Select * from MyControls"); 
    DataTable dt=new DataTable(); 

    adap.Fiil(dt); 

    foreach(DataRow dr in dt.Rows) 
    { 
     ThreadStart ts=delegate{ Sample1(dr) }; 
Thread th=new Thread(ts); 
th.start(); 

    } 

    } 

    public void Sample1(DataRow dr) 
    { 
    this.Invoke(new AddControlsDelegate(AddControls),new object[] {dr }); 
    } 
    public void AddControls(DataRow dr) 
    { 
    TextBox tx=new TextBox(); 
    tx.Name=dr["Id"].ToString(); 
    this.Controls.Add(tx); 

    } 

public delegate void AddControlsDelegate(DataRow dr); 

나는 그것이 두 번 3 시간, 4 시간

내 잘못을 시간을 같은 컨트롤을 추가 work.It 해달라고 나누었다이 코드와 함께 노력 해요? 당신은 루프 변수를 통해 닫는 감사

답변

2

:

foreach(DataRow dr in dt.Rows) 
{ 
    ThreadStart ts=delegate{ Sample1(dr) }; 
    ... 
} 

당신은 루프 변수 시간에서하지 그 가치의 폐쇄를 만드는 - 스레드가 될 것이기 때문에 단지 시작했다 약간의 시간이 지나면 루프가 완료되고 각 스레드는 마지막 시간에 루프 변수 의 값을 사용합니다.

foreach(DataRow dr in dt.Rows) 
{ 
    DataRow currentRow = dr; 
    ThreadStart ts=delegate{ Sample1(currentRow) }; 
    Thread th=new Thread(ts); 
    th.start(); 
} 

은 또한 당신이 거기 루프 변수 몇 가지를 통해 폐쇄를 만든 사실에서 제외 "Closing over the loop variable considered harmful"

+0

그것을 lot.But 컨트롤은 "ID"asceding 은 때로는 아마도 당신은 SQL을 변경해야합니다 – YardimaIhtiyaciOlan

+1

을 asceding 오지 와서해야하고 Id'하여 'ORDER를 포함 작업 덕분에 ... – Yahia

+0

@YardimaIhtiyaciOlan 다음에 추가 SQL에서 순서를 지정할 때 스레드가 실제로 실행되는 시점을 제어 할 수는 없으며 다른 접근 방식이 필요하다는 것을 알기 위해 순서가 보장되지 않습니다. 또한 현재 코드가별로 중요하지 않습니다. 다중 스레드를 사용하는 오버 헤드는 실제로하는 일에 가치가 없습니다. – BrokenGlass

0

를 참조하십시오

대신 루프 내에서 지역 변수를 만들고 위임에 사용 당신의 일반적인 접근법에 꽤 큰 문제가 있습니다.

먼저 DataTable의 각 행에 대해 하나의 스레드를 만드는 것은 좋은 생각이 아닙니다. 문제는 스레드를 생성하고 시작하는 것이 비용이며 많은 리소스를 소모합니다. 스레드 작성 방법과시기를 현명하게 선택해야합니다. 예를 들어 10,000 스레드가 실행중인 경우 (DataTable에 10,000 개의 해당 행이 있다고 가정) 잘 해결되지 않습니다.

ThreadPool을 사용하여 비동기 대의원 인 QueueUserWorkItem을 사용하거나 새로운 Task을 시작하는 경우 더 큰 문제가 있습니다. 다른 스레드에서 발생시키려는 작업이 UI 스레드로 다시 정렬됩니다. 이 경우 스레드를 사용하면 전혀 쓸모가 없습니다. 사실 스레드는 유용한 작업을 수행하지 않기 때문에 모든 것을 악화시킵니다. 그리고 아무것도 수행하지 않으려면 Control.Invoke을 통해 값 비싼 마샬링 작업이 필요합니다. 즉, UI 스레드는 작업자 스레드에게 무언가를 수행하라는 메시지를 표시하고 작업자 스레드는 돌아 서서 "나는 원하지 않습니다. 당신이 대신합니다."라고 말합니다.

더 나은 방법은 SQL 명령을 실행하고 DataTable을 다른 스레드에 채우는 것입니다. 완료되면 UI 스레드에서 폼에 TextBox 컨트롤을 모두 추가 할 수 있습니다. 사실, UI 요소를 사용하여 아무 것도하지 않으면 UI 스레드에서 수행해야하므로 여기에 수용 가능한 많은 옵션이 없습니다.