In attesa che l'attività termini prima di iterare

.net-4.0 c# foreach sqlbulkcopy

Domanda

Ho una funzione che legge ogni file da una directory e lo carica in un database. Non riesco a capire come aspettare che l'operazione finisca prima di tornare al ciclo foreach, poiché sembra che lo faccia subito, dove l'attività richiede alcuni secondi:

foreach (string file in Directory.EnumerateFiles(folderPath, "*.xml"))
{
    //load file
    currentReader = new XmlDataReader(transferInstructions, file);

    currentReader.RowsUploaded += new EventHandler<RowsUploadedEventArgs>(currentReader_RowsUploaded);
    currentReader.TableUploaded += new EventHandler<TableUploadedEventArgs>(currentReader_TableUploaded);
    currentTask = new Task(() => currentReader.executeBulkCopy(initialConnString, workingDatabase));
    currentTask.ContinueWith(task =>
    {
        cleanUp(task);
        //MessageBox.Show("Complete!");
    });
    currentTask.Start();
    writeResult("Started the transfer process.");
    cmdDataTransfer.Text = "CANCEL TRANSFER";
    cmdDataTransfer.ForeColor = Color.DarkRed;
    transferAction = () => cancelCurrentReader();   
}

Devo aspettare il punto in cui deve essere MessageBox.show prima di continuare il ciclo foreach. Ci vogliono alcuni secondi per arrivare a cleanUp (attività); //MessageBox.Show("Complete! "); sezione.

Grazie.

Risposta accettata

Il pattern async-awqait in C # 5 / .NET 4.5 è un abbinamento perfetto per questo. Vedo che l'hai taggato come .NET4, ma se puoi usare il pacchetto di targeting Async , c'è un modo molto elegante per farlo:

void Main()
{
    foreach (string file in Directory.EnumerateFiles(folderPath, "*.xml"))
    {
        currentReader = new XmlDataReader(transferInstructions, file); //load file
        currentReader.RowsUploaded += new EventHandler<RowsUploadedEventArgs>(currentReader_RowsUploaded);
        currentReader.TableUploaded += new EventHandler<TableUploadedEventArgs>(currentReader_TableUploaded);

        var task = Task.Factory.StartNew(() => currentReader.executeBulkCopy(initialConnString, workingDatabase));
        await task;

        cleanUp(task);
        MessageBox.Show("Complete!");
        writeResult("Started the transfer process.");
        cmdDataTransfer.Text = "CANCEL TRANSFER";
        cmdDataTransfer.ForeColor = Color.DarkRed;
        transferAction = () => cancelCurrentReader();   
    }
}

Se devi tenerlo VS2010, dovrai emulare ciò che async-attendi fa, qualcosa sulla falsariga di:

void MyForm()
{
    _syncContext = SynchronizationContext.Current;
    Execute(Directory.EnumerateFiles(folderPath, "*.xml").GetEnumerator());
}

void Execute(IEnumerator<string> files)
{
    if (!files.MoveNext())
    {
        files.Dispose();
        return;
    }
    Task.Factory.StartNew(() => Execute(files.Current)).ContinueWith(() => Execute(files));
}

public void Execute(string file)
{
    currentReader = new XmlDataReader(transferInstructions, file); //load file
    currentReader.RowsUploaded += new EventHandler<RowsUploadedEventArgs>(currentReader_RowsUploaded);
    currentReader.TableUploaded += new EventHandler<TableUploadedEventArgs>(currentReader_TableUploaded);
    () => currentReader.executeBulkCopy(initialConnString, workingDatabase);
    cleanUp(task);
    _syncContext.Send(updateGUI); 
    transferAction = () => cancelCurrentReader(); 
}
public void updateGUI()
{
    MessageBox.Show("Complete!");
    writeResult("Started the transfer process.");
    cmdDataTransfer.Text = "CANCEL TRANSFER";
    cmdDataTransfer.ForeColor = Color.DarkRed;
}

EDIT Ora che ci penso, c'è anche un modo molto più semplice. È possibile avere l'intero ciclo in esecuzione in un'attività a sé stante (delegando al contesto di sincronizzazione per il lavoro della GUI). Utilizzando le convenzioni del codice sopra:

Task.Factory.StartNew(() => 
{
    foreach (var file in Directory.EnumerateFiles(folderPath, "*.xml"))
        Execute(file);
}


Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow