2012-10-02 9 views
1

백그라운드 작업자를 사용하여 sqlserver의 일부 테이블을 업데이트하고 있습니다. progressbar max가 올바른 값으로 설정되고 progressbar 값이 증가되고 backgroundworker progresschanged가 올바른 값으로 올바르게 호출되지만 바는 진행되지 않습니다.백그라운드 작업자를 사용하여 진행 표시 줄을 진행하지 않습니다.

여기 background_dowork 메서드에 형태의 코드가 있습니다. 올바른 값으로 작동하는 updateProgressBarValue를 호출하는 루프가 있습니다. 여기

public InterfaceConvertLonLat() 
{ 
    InitializeComponent(); 
    Shown += new EventHandler(Form1_Shown); 
    backgroundWorker1.WorkerReportsProgress = true; 
    backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged); 
    backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork); 
} 

public void ConvertLonLat_Load(object sender, EventArgs e) 
{ 
} 

public void updateProgressBarValue() 
{ 
    progressBar1.Value++; 
    backgroundWorker1.ReportProgress(progressBar1.Value); 
} 

public void setProgressBarMax(int max) 
{ 
    progressBar1.Maximum = max; 
    MessageBox.Show("setprogressbarmax " + max); 
} 

public void Form1_Shown(object sender, EventArgs e) 
{  
    backgroundWorker1.RunWorkerAsync(); 
} 

public void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    convert.OSGB36ToWGS84("paf"); 
} 

public void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    progressBar1.Value = e.ProgressPercentage; 
} 

이 updateprogressbarvalue를 호출하는 다른 클래스에 포함 된 루프,이 해고되고 있으며 명시된 backgroundworker1_progressChanged 해고 그러나되었던대로 막대가 이동되지 않습니다.

con.setProgressBarMax(address.Tables[0].Rows.Count); 

foreach (DataRow LonLat in address.Tables[0].Rows) 
{ 
    con.updateProgressBarValue(); 
    Double lon = 0; 
    Double lat = 0; 
    lat = Convert.ToDouble(LonLat["LTO"]); 
    lon = Convert.ToDouble(LonLat["LGO"]); 
    LocalToWGS84(ref lat, ref lon, OGB_M); 

    cmd1.Parameters["@LTW"].Value = lat; 
    cmd1.Parameters["@LGW"].Value = lon; 

    string dbQuery1 = "update " + tableName + " set LTW = @LTW, LGW = @LGW"; 

    cmd1.CommandText = (dbQuery1); 
    cmd1.CommandType = CommandType.Text; 
    cmd1.Connection = conn; 
    cmd1.ExecuteNonQuery(); 
} 
} 
catch (Exception e) 
{ 
    MessageBox.Show("error converting: " + e.Message); 
} 
finally 
{ 
    conn.Close(); 
} 
+1

DoWork 내부에서'ReportProgress' 또는'updateProgressBarValue'를 호출하지 않습니까? – Tudor

+0

'DoWork' 메소드와'updateProgressBarValue' 메소드 사이에 어떤 연결도 보이지 않습니다. – Tudor

+0

저는 그 방법입니다 convert.OSGB36ToWGS84 ("paf")는 updateprogressbarvalue를 호출하는 클래스 내 다른 클래스에 있습니다 –

답변

2

당신이 그것을 업데이트가 필요로 진행 막대를 알려 배경 노동자에서 이벤트를 발생해야하는 진행 상황을보고. 다음을 사용하여이 작업을 수행 할 수 있습니다.

backgroundWorker1.ReportProgress(10); 

코드의 증가 된 진행 상태를 보여줄 필요가있는 값으로 변경하십시오. 진행 상태 변경 이벤트는 대부분 GUI와 동일한 스레드에서 실행되므로 크로스 스레드 문제가 없어야합니다. 한 가지 예외는 addin을 통해 Excel에서 양식을 호출 할 때 Excel이 주 스레드에있을 경우입니다.

+0

updateProgressBarValue()는 loop 내에서 호출되며 backgroundWorker1.ReportProgress (progressBar1.Value)를 호출합니다. –

+0

나는 progressBar1.Value ++가 다른 스레드의 값을 증가 시키려고 시도한다고 생각합니다. 시도하십시오 var progress = progressBar1.Value; 그런 다음 ReportProgress로 전달할 때 ++ 진행 – InContext

-2

이것은 Windows 양식의 UI가 자체 스레드/컨텍스트에서 실행 중이므로 발생할 수 있다고 생각합니다. 이 경우 UI를 조정하려면 Invoke을 사용해야 할 것입니다. 이 같은

뭔가 :

public void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    Invoke(new ProgressDelegate(UpdateProgress), e.ProgressPercentage); 
} 

delegate void ProgressDelegate(decimal value); 

private void UpdateProgress(decimal value) 
{ 
    progressBar1.Value = value; 
} 
+1

이것은 올바르지 않습니다. 'ProgressChanged' 이벤트 핸들러는 UI 스레드에서 실행됩니다. – Tudor

1

많은 문제가 있습니다. UpdateprogressBarValue()은 진행률 표시 줄의 값을 증가 시키지만 현재 호출 한 횟수/현재 값을 추적하지 않습니다. 따라서 101 번 호출하면 (0-100 범위로 가정) OutOfRangeException

DoWork() 메서드가 (직접 또는 이벤트 발생시) 업데이트를 전혀 호출하지 않는 것 같습니다.

이벤트를 사용하면이 작업을 수행 할 수 있지만 대리인 또는 익명의 기능을 사용하는 것이 좋습니다. 뭔가 같은 ...

public void setProgress(int value) { 
    progressBar1.invoke(delegate{ progressBar1.Value = value; } 
} 

후 바로 다음은 심각하게 잘못

+0

updateprogressBarValue는 테이블의 레코드 수에 의해 설정된 최대 값까지만 증가하므로 초과하지 않습니다. 백그라운드 작업자가 작업의 대부분을 수행하고 진행 막대를 업데이트 할 의도가 있다고 생각했습니다. –

+0

확장 된 코드 조각에서 백그라운드 작업자가 직접적으로 참조하고있는 아키텍처에 대해 약간의 확신이 없습니다. 'con' 변수를 통해'InterfaceConvertLonLat'에 연결하십시오 - 그래서 작업자는 (form?)을 생성 한 다음 다시 작업자를 참조합니다. 두 방향 모두에서 참조가 실행되고있는 것 같습니다. 어쨌든, 당신의 작업자 (쓰레드 A)는'con.updateProgressBarValue()'를 호출하는데, 이는 차례대로'progressBar1.value()'를 UI 쓰레드의 컨트롤 (문제의 근원이 될 것입니다)을 증가시킵니다. 실행 흐름에 대한 명확한 설명을 제공 할 수 있습니까? – Basic

1

당신의 DoWork() 방법에서 setProgress(progressBar1.MaxValue)을 통해 setProgress(0) 전화 :

public void updateProgressBarValue() 
{ 
    progressBar1.Value++; // not thread-safe 
    backgroundWorker1.ReportProgress(progressBar1.Value); 

} 

ReportProgress()

이 폼 DoWork 호출 할 의도가해야 심지어 Control 속성을 읽지 않습니다.
foreach 루프에 카운터를 유지하고 진행 메커니즘에 카운터를 공급해야합니다.

이제는 이동하지 않는 이유를 직접 나타내지는 않지만 완료된 처리기가 없습니다. 프로세스가 완료되었다고 확신합니까?

예외가 DoWork를 벗어나면 어떤 일이 발생했는지 결코 알 수 없습니다.

0
private void Form1_Load(object sender, System.EventArgs e) 
{ 
    // Start the BackgroundWorker. 
    backgroundWorker1.RunWorkerAsync(); 
} 

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    for (int i = 1; i <= 100; i++) 
    { 
    // Wait 100 milliseconds. 
    Thread.Sleep(100); 
    // Report progress. 
    backgroundWorker1.ReportProgress(i); 
    } 
} 

private void backgroundWorker1_ProgressChanged(object sender, progress e) 
{ 
    // Change the value of the ProgressBar to the BackgroundWorker progress. 
    progressBar1.Value = e.ProgressPercentage; 
    // Set the text. 
    this.Text = e.ProgressPercentage.ToString(); 
} 
관련 문제