Long processes in C#

Asked

Viewed 1,320 times

3

I need to do a routine where the user will upload a data load file, and C# will process it and save it in the database, without giving time-out and showing the process progress to the user.

My question is: how to do?

I have no idea how to do or how to search in Google. Any suggestions?

  • Are you looking to process the file in C# while uploading? That is, before the upload is finished, do you already want C# to be processing the file? That’s it?

  • Don’t do that. There are so many things that can go wrong. You can control the timeout of IIS and ASP.NET but you cannot control the browser timeout. ASP.ET was not made for heavy processing. You should immediately put the file in a BD or disk and have an external service to process it. To give information to the user you could use Polling or use Signalr to notify.

  • Google search suggestion "Async file upload Asp.net mvc". Which will lead you to the use of asyncronos methods. One of the results I found in English was https://damienbod.wordpress.com/2013/09/03/mvc-async-file-upload/

4 answers

1

I do not believe that it is the best solution to process an already uploaded file. Ideally it would just move the file to a folder on your server and have a service that does Processing for you.

This prevents you from locking your application into the ISS and the database by doing a very heavy processing, and takes away that responsibility from your Website or Winforms to do what in fact would not be their responsibility, facilitating future maintenance on a code that is likely to be complex.

There is no way I can suggest an implementation of how to save the File since I don’t know if you use MVC, Web Forms or Win Forms.

But in the case of Windows Service you need to use a File System Watcher object to monitor the receiving of files in the server folder as an example:

public partial class ProcessadorDeArquivo
{
     protected FileSystemWatcher _fileSystemWatcher { get; set; }

     public ProcessadorDeArquivo()
     {
          _fileSystemWatcher = new FileSystemWatcher(@"C:\Arquivos"); //Pasta que será utilizada para salva os arquivos.
          _fileSystemWatcher.Filter = ".txt" //ExtensãoDoArquivo
          _fileSystemWatcher.Created += FileSystemWatcherCreated;
          _fileSystemWatcher.EnableRaisingEvents = true;
     }

     /// <summary>
     /// Quando um arquivo é criado na pasta assistida esse evento é disparado
     /// </summary>
     protected void FileSystemWatcherCreated(object sender, FileSystemEventArgs e)
     {
         ProcessarArquivos(e.FullPath); //Método que teria toda a regra de processar.
     }
}

EDIT (ASP.NET MVC)

//VIEW
@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype ="multipart/form-    data" }))
{
<input type="arquivo" name="arquivo" />
<input type="submit" value="salvar" />
}

//CONTROLLER

    public ActionResult Index(HttpPostedFileBase arquivo)
{
    // Verify that the user selected a file
    if (arquivo != null) 
    {
        var nome = Path.GetFileName(arquivo.FileName);
        arquivo.SaveAs(@"C:\Arquivos\" + nome);
    }
    return View(); 
}
  • It’s ASP.NET MVC. It’s one of the question tags.

  • Edited with a simple example, I hadn’t noticed it was MVC.

  • What would be the best way to make my ASP MVC 4 application, do long processing without bursting the time out and show progress to the user? Example financial control (generating billets) that is initialized by the user.

  • There are ways and ways to show Progress, I don’t see why it has to be in real time. For all I have seen and worked on project I find it much better to "outsource" these more expensive processing. Timeout exists for a reason and if your processing is exceeding the default value it is because something in Architecture is wrong. You can display the statement as "Sent", "Processing" and "Completed" /"Processing Failed" according to a flag on your service.

  • How can I from the View call such a process? What would be the best way? I already know that the boot I would do by ajax, but internally I would have to mount a thread? or what?

1

In the case of Timeout you can make the configuration on the web.config itself

<system.web>
<authentication mode="Forms">
      <forms timeout="50"/>
</authentication>
<sessionState timeout="60"  />
</system.web>

Thus setting the time limit for Session and Forms.

0

Setup

You will need to make some settings before allowing the user to make a large upload to your system:

  • upload limit size

  • maximum request time

Configuration example:

<system.web> 
    <httpRuntime maxRequestLength="157286400" executionTimeout="900" /> 
</system.web>

<system.webServer> 
    <security> 
        <requestFiltering> 
                <requestLimits maxAllowedContentLength="157286400" /> 
             </requestFiltering> 
    </security> 
</system.webServer>

Plugin to upload with progress

I recommend a file upload plugin that supports tracking upload progress: http://blueimp.github.io/jQuery-File-Upload/

I’ve used this plugin in some projects, it’s really very good.

0

Using AJAX upload. There is a Nuget package that configures jQuery for this:

Install-Package jQuery.Ajaxupload

Example:

<script>

    // Variável que guarda seus arquivos
    var files;

    // Eventos que adicionam arquivos à variável de arquivos
    $('input[type=file]').on('change', prepareUpload);

    function prepareUpload(event)
    {
      files = event.target.files;
    }

    $('form').on('submit', uploadFiles);

    function uploadFiles(event)
    {
        event.stopPropagation(); // Parar todos os processamentos
        event.preventDefault();

        // Coloque aqui sua barra de progresso ou seu ícone de loading...

        // Crie um objeto FormData e adicione os arquivos
        var data = new FormData();

        $.each(files, function(key, value)
        {
            data.append(key, value);
        });

        $.ajax({
            url: 'SeuController/Upload',
            type: 'POST',
            data: data,
            cache: false,
            dataType: 'json',
            processData: false, // Não processar os arquivos
            contentType: false, 
            success: function(data, textStatus, jqXHR)
            {
                if(typeof data.error === 'undefined')
                {
                    // Sucesso, envia dados para controller
                    submitForm(event, data);
                }
                else
                {
                    // Erros
                    console.log('ERROS: ' + data.error);
                }
            },
            error: function(jqXHR, textStatus, errorThrown)
            {
                // Mais erros
                console.log('ERRORS: ' + textStatus);
                // Desligue seu ícone de loading aqui
            }
        });
    }
</script>
  • But the problem is the processing, how do I make a pessado processing without giving timeout? The file load was an example, but I have processes that can delay and generate timeout and did not want this to happen.

Browser other questions tagged

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