2008-12-15 13 views
6

Quiero que mi trabajador de fondo agregue elementos a un cuadro de lista, parece hacerlo cuando se depura pero el cuadro de lista no muestra los valores. Sospecho que esto tiene algo que ver con la adición de elementos mientras estoy dentro del hilo de trabajo en segundo plano, ¿debo agregarlos a una matriz y llenar el cuadro de lista de la matriz durante backgroundWorker1_RunWorkerCompleted?C# ¿Puedo agregar valores a un cuadro de lista con un hilo de fondo?

Gracias por la ayuda.

Respuesta

1

Usted puede añadirlos mientras que en un subproceso de fondo a través de:

Form.Invoke 

o

Form.BeginInvoke 

que se requieren para ordenar la llamada de un subproceso de fondo para un hilo principal interfaz de usuario. Sin embargo, estoy bastante seguro de que BackgroundWorker ofrece un evento que se invoca automáticamente en el hilo de primer plano y que debería poder actualizar este evento sin ningún problema. Esto es "ProgressChanged" que puede ser activado por el proceso de trabajo en segundo plano llamando a ReportProgress.

¿Ha intentado llamar al .Refresh() en el cuadro de lista también?

6

Puede, pero debe avisar a su trabajador social que informe el estado y enviar la entrada para el cuadro con el estado actual de ese evento. En el método para ese evento, puede acceder al cuadro y poner el nuevo valor.

De lo contrario, debe invocar manualmente.

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

Un inconveniente de este método sería que no se puede encerrar población cuadro de lista dentro de BeginUpdate/EndUpdate. –

+0

agrego 500k elementos al cuadro de lista, pero aún está congelando la UI del componente bw. alguna idea por qué? – Smith

+0

En ese caso, le recomendaría que no agregue los elementos uno por uno, pero tal vez informe el progreso de las 100 o 1000 iteraciones con un grupo de elementos para agregar. El ProgressChanged-Event debe invocarse en el hilo principal, por lo que llamarlo a menudo congela la GUI. –

0
+0

Esto no es muy útil, ya que uno primero debe leer todo el hilo. –

+0

¡Eso es realmente un problema para ti! Este es solo un enlace útil para una discusión similar. Todas las respuestas son útiles para obtener una mejor comprensión y el hilo no * que * largo. – paul

13

Puede utilizar invocación de la siguiente manera:

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

Sí, pero el BackgroundWorker lo hace automáticamente con el evento. –

+0

Lo sé, solo estoy brindando una alternativa;) –

+0

Las alternativas siempre son buenas, la sensación de tener una elección es esencial para la matriz ;-) –

1

puedo añadir funciones como la siguiente para que pueda añadir elementos al cuadro de lista de cualquiera de los principales hilos de rosca o de fondo. Este hilo comprueba si es necesaria una Invocación y luego usa Invocar si es necesario.

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() función resolverá el problema.

1

si está intentando actualizar una base de datos. Desde un cuadro de lista, sugeriría crear un conjunto de datos.

por ejemplo, si está haciendo algo para cada elemento en una base de datos. Copie el conjunto de datos de la base de datos, creando un nuevo conjunto de datos y declarando por mainDataset.

por ejemplo: // el conjunto de datos gridview es DataSet1 (artículos añadiendo uno por uno)

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(); 
} 
Cuestiones relacionadas