2008-12-15 6 views
6

Chcę, aby mój pracownik tła dodał elementy do pola listy, wydaje się, że to robi podczas debugowania, ale pole listy nie pokazuje wartości. Podejrzewam, że jest to coś wspólnego z dodawaniem elementów podczas działania wątku roboczego tła, czy muszę dodać je do tablicy, a następnie zapełnić pole listy z tablicy podczas backgroundWorker1_RunWorkerCompleted?C# Czy mogę dodać wartości do pola listy za pomocą wątku tła?

Dzięki za pomoc.

Odpowiedz

1

Możesz dodać je natomiast w wątku tła poprzez:

Form.Invoke 

lub

Form.BeginInvoke 

które są wymagane do Marshalla wywołanie z wątku tła do głównego wątku UI. Jednak jestem całkiem pewny, że BackgroundWorker oferuje zdarzenie, które jest automatycznie wywoływane w wątku pierwszoplanowym i powinieneś być w stanie zaktualizować to wydarzenie bez żadnych problemów. To jest "ProgressChanged", który może być uruchomiony przez proces roboczy w tle przez wywołanie ReportProgress.

Czy próbowałeś również dzwonić pod numer .Refresh()?

6

Możesz, ale musisz doradzić swojemu pracownikowi, aby zgłosił stan i wysłać dane wejściowe do skrzynki z bieżącym stanem na to wydarzenie. W metodzie tego zdarzenia można uzyskać dostęp do skrzynki i wprowadzić nową wartość.

W przeciwnym razie należy wywołać ręcznie.

public Form1() 
     { 
      InitializeComponent(); 

      BackgroundWorker bw = new BackgroundWorker(); 
      bw.WorkerReportsProgress = true; 
      bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged); 
      bw.DoWork += new DoWorkEventHandler(bw_DoWork); 
      bw.RunWorkerAsync(); 
     } 

     void bw_DoWork(object sender, DoWorkEventArgs e) 
     { 
      for (int i = 0; i < 10; i++) 
      { 
       ((BackgroundWorker)sender).ReportProgress(0, i.ToString()); 
      } 
     } 

     void bw_ProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      listBox1.Items.Add((string)e.UserState); 
     } 
+0

Wadą tej metody (Dodaję jeden po drugim) jest to, że nie można ująć populację listbox wewnątrz BeginUpdate/EndUpdate. –

+0

Dodaję 500k pozycji do listbox, ale jego nadal zamrożenie th UI jest komponent bw. jakieś pomysły, dlaczego? – Smith

+0

W takim przypadku nie zaleca się dodawania elementów jeden po drugim, ale może zgłosić postęp tylko w przypadku 100 lub 1000 iteracji z pęczkiem elementów do dodania. Zdarzenie ProgressChanged musi zostać wywołane w wątku głównym, dlatego wywołanie go często powoduje zawieszenie GUI. –

0
+0

To niezbyt użyteczne, ponieważ trzeba najpierw przeczytać cały wątek. –

+0

Czy to naprawdę problem? To po prostu pomocny link do podobnej dyskusji. Wszystkie odpowiedzi są przydatne dla lepszego zrozumienia i wątku, który nie * jest * długi. – paul

13

Można użyć Invoke tak:

private void AddToListBox(object oo) 
{ 
    Invoke(new MethodInvoker(
        delegate { listBox.Items.Add(oo); } 
        )); 
} 
+0

Tak, ale BackgroundWorker robi to automatycznie ze zdarzeniem. –

+0

Wiem, że dostarczam tylko alternatywy;) –

+0

Alternatywy są zawsze dobre, odczucie posiadania wyboru jest niezbędne dla matrycy ;-) –

1

dodam funkcje jak poniżej, aby można było dodać elementy do listy albo od wątku głównego lub tła wątkach. Wątek ten sprawdza, czy Invoke jest konieczne, a następnie używa Invoke, jeśli jest to konieczne.

delegate void AddListItemDelegate(string name,object otherInfoNeeded); 

    private void 
    AddListItem(
     string name, 
     object otherInfoNeeded 
    ) 
    { 
    if (InvokeRequired) 
    { 
     BeginInvoke(new AddListItemDelegate(AddListItem), name, otherInfoNeeded 
     return; 
    } 

    ... add code to create list box item and insert in list here ... 
    } 
0

Application.Doevents() funkcja rozwiąże problem.

1

jeśli próbujesz zaktualizować bazę danych. Z listbox sugerowałbym utworzenie zbioru danych.

na przykład, jeśli robisz coś dla każdej pozycji w bazie danych. Skopiuj zestaw danych bazy danych, tworząc nowy zestaw danych i deklarując przez mainDataset.

na przykład: // gridview zestaw danych jest DataSet1

BackgroundWorker_DoWork(object sender, DoWorkArgs e) 
{ 
    Dataset dataset2 = dataset1; 
    foreach(DataGridViewRow row in GridView) 
    { 
     //do some work 
     dataset2.Main.AddMainRow(values to add); 
     dataset2.AcceptChanges(); 
    } 
} 


BackgroundWorker_WorkCompleted(object sender, DoWorkArgs e) 
{ 
    //Forces UI thread to valitdate dataset 
    dataset2.update(); 

    // Sets file Path 
    string FilePath = "Some Path to file"; 

    dataset2.writexml(FilePath, XmlWriteOptions.WriteSchema); 

    //if you use xml to fill your dataset filepath to write should equal path to dataset1 xml 
    dataset1.Refresh(); 
} 
Powiązane problemy