Search for objects in Runtime

Asked

Viewed 53 times

1

I have an application that will make simultaneous downloads of different data sources. I have a DataGridView that will receive the result of a select and from the amount of lines that come from that result I will have the same amount of TabPages. Each TabPage will have a Textbox to record the progress of downloads. Downloads are made in periods, which are also variable, depends on the download configuration. That said, I have the following situation... Like every time I run the query, I assemble new objects and even create the Timer and the BackgroundWorker to perform all actions.

To avoid creating too many tabs, I’m running through the TabControl in a foreach and using the TabPage.Dispose() to release the resources of the application. Only I haven’t found a way to do the same with the Timer and the BackgroundWorker. How could I find the two to "kill" them at runtime?

Update: Object creation code

    private void createLogColTab(int pCodigoCol,
                                    string pTipoCol)
    {
        TabPage tbpNew = new TabPage();
        tbpNew.Tag = pCodigoCol.ToString();
        tbpNew.Name = "tbpLogCol" + clsGeneric.TruncateLongString(pCodigoCol.ToString(), 3, "R", "0");
        tbpNew.Text = pTipoCol;
        tbpNew.Height = panel1.Height;
        tbpNew.Width = panel1.Width;

        TextBox txtResult = new TextBox();
        txtResult.Name = "txtLogCol" + clsGeneric.TruncateLongString(pCodigoCol.ToString(), 3, "R", "0");
        txtResult.Multiline = true;
        txtResult.Height = tbpNew.Height;
        txtResult.Width = tbpNew.Width;
        txtResult.Text = tbpNew.Name;
        txtResult.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right | AnchorStyles.Left | AnchorStyles.Top);
        txtResult.Tag = pCodigoCol.ToString();

        Timer tmrNew = new Timer();
        tmrNew.Tag = pCodigoCol.ToString();

        BackgroundWorker bgwNew = new BackgroundWorker();
        bgwNew.WorkerReportsProgress = true;
        bgwNew.DoWork += bgwMain_DoWork;
        bgwNew.ProgressChanged += bgwMain_ProgressChanged;
        bgwNew.RunWorkerCompleted += bgwMain_RunWorkerCompleted;

        tbcLogColeta.TabPages.Add(tbpNew);
    }

1 answer

2


The Timer has an event Elapsed (Timer.Elapsed) where you can check (with a global variable) if this timer still needs to be run. If you don’t need it, you disable it.

In the case of Backgroundworker, he owns the property WorkerSupportsCancellation:

bw.WorkerSupportsCancellation = true;

Where you can cancel the execution:

private void bw_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;

    for (int i = 1; (i <= 10); i++)
    {
        if ((worker.CancellationPending == true))
        {
            e.Cancel = true;
            break;
        }
        else
        {
            // Perform a time consuming operation and report progress.
            System.Threading.Thread.Sleep(500);
            worker.ReportProgress((i * 10));
        }
    }
}

In the links below you have examples of this use:

https://msdn.microsoft.com/pt-br/library/system.componentmodel.backgroundworker(v=vs.110). aspx#Anchor_7

https://msdn.microsoft.com/en-us/library/cc221403(v=vs.95). aspx#Anchor_1

But in both cases, the worker is declared global. Could you do that in your case? Declare a list (or dictionary) of Workers globally?


EDIT

As we speak about the global dictionary:

// Dicionários:
private Dictionary<string, Timer> _allTimers = new Dictionary<string, Timer>();
private Dictionary<string, BackgroundWorker> _allWorkers = new Dictionary<string, BackgroundWorker>();

private void createLogColTab(int pCodigoCol,
                                string pTipoCol)
{
    TabPage tbpNew = new TabPage();
    tbpNew.Tag = pCodigoCol.ToString();
    tbpNew.Name = "tbpLogCol" + clsGeneric.TruncateLongString(pCodigoCol.ToString(), 3, "R", "0");
    tbpNew.Text = pTipoCol;
    tbpNew.Height = panel1.Height;
    tbpNew.Width = panel1.Width;

    TextBox txtResult = new TextBox();
    txtResult.Name = "txtLogCol" + clsGeneric.TruncateLongString(pCodigoCol.ToString(), 3, "R", "0");
    txtResult.Multiline = true;
    txtResult.Height = tbpNew.Height;
    txtResult.Width = tbpNew.Width;
    txtResult.Text = tbpNew.Name;
    txtResult.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right | AnchorStyles.Left | AnchorStyles.Top);
    txtResult.Tag = pCodigoCol.ToString();

    Timer tmrNew = new Timer();
    tmrNew.Tag = pCodigoCol.ToString();

    // Adicionar ao dicionário:
    _allTimers.Add(pCodigoCol.ToString(), tmrNew);

    BackgroundWorker bgwNew = new BackgroundWorker();
    bgwNew.WorkerReportsProgress = true;
    bgwNew.DoWork += bgwMain_DoWork;
    bgwNew.ProgressChanged += bgwMain_ProgressChanged;
    bgwNew.RunWorkerCompleted += bgwMain_RunWorkerCompleted;

    // Adicionar ao dicionário:
    _allWorkers.Add(pCodigoCol.ToString(), bgwNew);

    tbcLogColeta.TabPages.Add(tbpNew);
}
  • So the problem is that I create the Timer and the BackgroundWorker dynamically for every line I have, if I return 3 lines from the BD, I will have 3 Timers and 3 BackgroundWorkers, because the system has to do all 3 operations simultaneously. If you see the code I just included, I can’t link the Timer or the BackgroundWorker.

  • You can’t mount a key string single for each row and create a Dictionary with this string as key and the Timer/BackgroundWorker as a value?

  • I included an example in the answer.

  • Your solution is perfect Rick, I will implement it. But just out of curiosity, Tabpage has a property called "Container", it has some way to use this property to include Timer and Backgroundworker?

  • Man, I never used that Tabpage container. Looking at the documentation I saw that the Timer inherits from Icomponent and the Container has a list of Components (which are Icomponent). But I don’t know if it would work or how. Just testing to find out... : P

Browser other questions tagged

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