Do not pause the process, but stop it completely
The ideal in a long process is to be able to pick up where you left off if you interrupt.
Otherwise, if it is unintentionally interrupted, you will either have to start and redo everything that has already been done or end up with inconsistencies like having the source data entered into the destination twice.
Imagine you pause the process and when you come back two hours later to continue the application is no longer there because the machine has been restarted.
Some ideas on how to make your process resilient to interruptions and be able to pick up where you left off:
Rename already processed files (for example, from img file. for processed.img file) and when it is time to start processing select only those whose name is different from that.
Move files already processed to another folder.
Create a text file where you insert the name of each already processed file. During processing then, you ignore the files that are on the list.
Create a table in the database for the same purpose as the text file described above. The difference is that instead of keeping in a text file the names of the files already processed, you will keep them in the database.
How to implement process interruption:
Once you have chosen the method for resuming the process, you can implement not a pause in this process but rather a complete interruption of this process. When you touch it back, it’s still where it left off. Even if your application is terminated or the machine is shut down or the database is unavailable between interruption and resumption.
// declara um token que permite invocar o cancelamento
CancellationTokenSource token = null;
// declara o método do click no botão como assíncrono (async)
private async void btnProcessar_Click(object sender, EventArgs e)
{
// cria uma instância do token de cancelamento
token = new CancellationTokenSource();
// obtém o token que será passado para o método que processa os arquivos
CancellationToken ct = token.Token;
// invoca o processamento dos arquivos de maneira assíncrona
// tratando o cancelamento e os erros que possam ocorrer
try
{
await Task.Run(() => ProcessaArquivos(ct));
}
catch (OperationCanceledException)
{
MessageBox.Show("Processo cancelado");
}
catch (Exception ex)
{
MessageBox.Show("O processo falhou: " + ex.ToString());
}
}
private void btnCancelar_Click(object sender, EventArgs e)
{
// invoca o cancelamento do processamento
if (token != null)
{
token.Cancel();
}
}
// processamento em si
public async Task ProcessaArquivos(CancellationToken ct)
{
DirectoryInfo di = new DirectoryInfo(pastaOriginal);
FileInfo[] arquivos = di.GetFiles();
int quantidade = arquivos.Length;
for (int i = 0; i < quantidade; i++)
{
// interrompe o processo lançando exceção caso tenha sido cancelado
ct.ThrowIfCancellationRequested();
// sqlComando = .....;
// aqui você registra que já foi processado segundo uma das idéias que passei
}
}
Actually pausing the app:
Now, if for various reasons I don’t know the pause button is more convenient, you can still use the above code with a few changes.
You should give a wider scope to control variables, as they should only be initialized the first time the process is started.
Then declare them as private in class:
private DirectoryInfo di;
private FileInfo[] arquivos;
private int quantidade;
private int quantidadeJaProcessada;
Create a method to initialize these variables only once:
private void inicializa()
{
if (di != null)
{
di = new DirectoryInfo(pastaOriginal);
arquivos = di.GetFiles();
quantidade = arquivos.Length;
quantidadeJaProcessada = 0;
}
}
On the button that triggers the processing, call the initializer before calling the process.
try
{
inicializa();
await Task.Run(() => ProcessaArquivos(ct));
}
// ...
And slightly change the processing loop so that it records where the process stopped and then it can continue from there:
public async Task ProcessaArquivos(CancellationToken ct)
{
// começa do Zero ou continua de onde parou
for (int i = quantidadeJaProcessada; i < quantidade; i++)
{
// verifica se foi cancelado
if (ct.IsCancellationRequested)
{
// registra quantos já foram processados, para continuar de onde parou
quantidadeJaProcessada = i;
ct.ThrowIfCancellationRequested();
}
//sqlComando = .....;
}
}
Take a look at [tour]. You can accept an answer if it solved your problem. You can vote on every post on the site as well. Did any help you more? You need something to be improved?
– Maniero