Report Error while copying files and folders using Threadpool

Asked

Viewed 71 times

0

I have a Windows Form application which copies files and folders to various networked machines.

When the copy is not possible, the name of the machine is added to a list and, at the end, I present in a Listbox.

The problem is that every time you fire an exception at one of the threads I can’t give a throw Ex to add to this list.

public class Processo
{
    private ManualResetEvent _eventoReset;
    private int _threadIndex;
    private string _destino;
    private string _origem;

    public Processo(ManualResetEvent eventoReset, string origem, string destino)
    {
        this._eventoReset = eventoReset;
        this._origem = origem;
        this._destino = destino;
    }

    public void ThreadPoolCallback(Object threadContextIndex)
    {
        this._threadIndex = (int)threadContextIndex;
        ExecutaTarefas();
        this._eventoReset.Set();
    }

    private void ExecutaTarefas()
    {
        try
        {
            FileSystem.CopyDirectory(_origem, _destino, true);
        }
        catch (Exception Ex)
        {
            throw Ex;
        }            
    }
}

In applying

int numeroDeElementos = maquinas.Count();

        ManualResetEvent[] statusEventos = new ManualResetEvent[numeroDeElementos];            
        Processo[] tarefaArray = new Processo[numeroDeElementos];

        for (int i = 0; i < maquinas.Count(); i++)
        {
            try
            {
                Ping ping = new Ping();
                PingReply retorno = ping.Send(maquinas[i].pc);

                if (retorno.Status == IPStatus.Success)
                {
                    statusEventos[i] = new ManualResetEvent(false);                       
                    Processo thr = new Processo(statusEventos[i], origem, destino));

                    tarefaArray[i] = thr;                        
                    ThreadPool.QueueUserWorkItem(thr.ThreadPoolCallback, i);                          
                }
                else
                {
                    listaMaquinas.Add(string.Format("{0} Fila: {1} Posição: {2} não foi possivel conectar ao computador. ", maquinas[i].auto, maquinas[i].fila, maquinas[i].posicao));
                }
            }                
            catch (Exception ex)
            {
                listaMaquinas.Add(string.Format("{0} - {1} - Fila:{2} - Posição:{3} - Erro: {4}", maquinas[i].auto, maquinas[i].pc, maquinas[i].fila, maquinas[i].posicao, ex.Message));
            }

            progressBar1.Value = x;
            x += 1;
        }
 foreach (WaitHandle doneEvent in statusEventos)
        {
            if (doneEvent != null)
            {
                doneEvent.WaitOne();
            }
        }

        if (listaMaquinas.Count() > 0)
        {
            listBox1.DataSource = listaMaquinas;
            MessageBox.Show("As maquinas listadas não puderam ser atualizadas.");
        }
        else
        {
            MessageBox.Show("Atualização concluida com sucesso.");
        }
  • Good thing you can’t get one throw ex;. It is the last thing you should do with an exception. Or perhaps penultimate, capture Exception also very wrong. I wrote a huge amount of answers on the subject because almost no one knows how to use exceptions. There is a lot to read and should not stop only in my answers, but it is essential to learn to use the resource correctly. http://answall.com/search?q=user:101+[exce%C3%A7%C3%A3o]

1 answer

1

You’re making some mistakes in your code - for example by throwing an exception inside a thread and hoping to catch it in a catch outside of it (that’s not how it works).

The code below is almost a pseudocode, only to, along with the comments I added, give an idea of how to proceed:

private void ExecutaTarefas()
{
    try
    {
        FileSystem.CopyDirectory(_origem, _destino, true);
    }
    catch (Exception Ex)
    {
        // não relance a exceção e nem lance nenhuma exceção
        // que você não vá tratar dentro da própria thread a não ser que
        // você assine os eventos de "Application" para tratamento de exceções em threads.

        // em vez disso, registro o erro:

        this.erro = "não foi possível copiar " + _origem + " para " + _destino
    }            
}

...

    for (int i = 0; i < maquinas.Count(); i++)
    {
        try
        {
            Ping ping = new Ping();
            PingReply retorno = ping.Send(maquinas[i].pc);

            if (retorno.Status == IPStatus.Success)
            {
                statusEventos[i] = new ManualResetEvent(false);                       
                Processo thr = new Processo(statusEventos[i], origem, destino));

                tarefaArray[i] = thr;                        
                ThreadPool.QueueUserWorkItem(thr.ThreadPoolCallback, i);                          
            }
            else
            {
                listaMaquinas.Add(string.Format("{0} Fila: {1} Posição: {2} não foi possivel conectar ao computador. ", maquinas[i].auto, maquinas[i].fila, maquinas[i].posicao));
            }
        }                
        catch (Exception ex)
        {
            // Não espere capturar aqui a exceção lançada dentro da thread pois isso não vai funcionar!
            // Provavelmente você pode eliminar esse tratamento de exceção.
        }

You can replace the below loop

    foreach (WaitHandle doneEvent in statusEventos)
    {
        if (doneEvent != null)
        {
            doneEvent.WaitOne();
        }
    }

For:

WaitHandle.WaitAll(statusEventos)

Finally, after all threads are finished, you go through all your processes and check which ones failed:

foreach (Processo processo: tarefaArray)
{
    if (processo.erro != null)
        listaMaquinas.Add(processo.erro);
}

I repeat that it is only a logical idea for the solution of the problem! Checking if the property "error" is null, for example, can be very simple. But the general idea is:

  • capture the exception within the thread itself;
  • record error details in properties of the process you executed as thread;
  • once the thread is completed, check the properties of the process to see its results.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.