Polêmica

Claro que sim, mas não vejo onde isso seja relevante para a discussão.

Estava só falando que possuir o mesmo mecanismo para se usar quando for conveniente, com uma sintaxe simples e ergonômica, com outros recursos que dão suporte fácil a isso (como co-rotinas) e se aproveitando ao máximo do potencial benéfico do assincronismo é positivo no .Net. O Java ainda está anos luz atrás disso. E o JavaScript, que é altamente dependente disso, está propondo só na versão 7 chegar ao que o .Net já tem hoje. Por isso falei para não menosprezarem a capacidade de integração do criador do .Net.

Em momento nenhum falei que impor esse modelo para absolutamente tudo, como faz o JavaScript, seria positivo. Até porque, o modelo single-threaded do JavaScript não permite que nós criemos nossos próprias rotinas que rodarão assincronamente. Só permite que esperemos por o que o browser já implemente por padrão.

[quote=javaflex][quote=lkbm][quote=javaflex]
Não me refiro a desempenho ou onde o processo pesado vai rodar, mas sobre o limite de requests ocupadas no servidor web, onde seja la onde for rodar o processo pesado, a thread do request não vai ficar travada.[/quote]

Se o cliente precisa saber o resultado da operação, ele vai ter que esperar na thread ou vai ter que fazer outra requisição para obter a resposta. Isso aumenta, não diminui o número de requests ao servidor.

De qualquer maneira, a decisão de travar é do programador da aplicação e depende do custo da operação a ser realizada (que é conhecido pelo programador no momento da codificação). Ao meu ver, não faz muito sentido o desenvolvedor basear essa decisão no número de requests que o servidor web em produção vai estar configurado para suportar, porque geralmente ele não tem essa informação enquanto esta desenvolvendo a aplicação.[/quote]
Tambem nao me refiro ao cliente, ele vai esperar sim, mas a thread do request gerenciada pelo webserver nao vai estar travada pela efetiva execucao do processo pesado. Existem sim casos de limitação, normalmente o erro retornado quando estoura no IIS é “Server too busy”, clássico ocorrer em hospedagens compartilhadas. No Java estou por fora, não tenho certeza mas parece que no Tomcat por exemplo tem algo relacionado a “maxThreads”.[/quote]

concordo se usar hospedagens compartilhadas vai ocorrer vários casos de limitação.

[quote=ViniGodoy]
Claro que sim, mas não vejo onde isso seja relevante para a discussão.

Estava só falando que possuir o mesmo mecanismo para se usar quando for conveniente, com uma sintaxe simples e ergonômica, com outros recursos que dão suporte fácil a isso (como co-rotinas) e se aproveitando ao máximo do potencial benéfico do assincronismo é positivo no .Net. O Java ainda está anos luz atrás disso. E o JavaScript, que é altamente dependente disso, está propondo só na versão 7 chegar ao que o .Net já tem hoje. Por isso falei para não menosprezarem a capacidade de integração do criador do .Net.

Em momento nenhum falei que impor esse modelo para absolutamente tudo, como faz o JavaScript, seria positivo. Até porque, o modelo single-threaded do JavaScript não permite que nós criemos nossos próprias rotinas que rodarão assincronamente. Só permite que esperemos por o que o browser já implemente por padrão.[/quote]

JS chegar ao que .net tem hoje? rs

Porque acha que isso seria possível ou desejável?

[quote=ViniGodoy]
Isso é válido para qualquer linguagem. Você irá disparar processos dessa maneira em qualquer linguagem. Java, C# ou JavaScript. E vai querer espera-los. Não é à toa que já existem APIs para isso no Java - como boa parte do pacote java.util.synchronized.[/quote]

Aqui você deve estar se referindo ao pacote java.util.concurrent.
Abraço

Não. Usa-se async também quando você quer disparar diversas operações assíncronas e aguardar por seu resultado em ordem. Um exemplo disso é o que é feito nessa aplicação para explicar os Promises: http://www.html5rocks.com/en/tutorials/es6/promises/?redirect_from_locale=pt

O Java tem APIs para esse tipo de tratamento. Chamam Future e Callable.[/quote]

Isso mesmo, JEE 6.
Usamos por aqui, é bem interessante, mas é usado em situações mais específicas, como as citadas pelos colegas e você.

[quote=lkbm]JS chegar ao que .net tem hoje? rs

Porque acha que isso seria possível ou desejável?[/quote]

Estou me referindo a essa proposta aqui:

Estamos falando da parte de assincronia, não do .Net framework inteiro.

Mesmo não querendo levar a discussão para Java X .Net eu tenho que confessar, eu relutei muito (muito mesmo) em trabalhar com .Net, eu já estava trabalhando com java e finalmente tinha me familiarizado com o Java SE (core) e estava começando a mandar bem no Spring, Hibernate etc etc… Surgiu um projeto pra ganhar o dobro em .Net, pensei pensei… e decidi arriscar, não me arrependo nem um pouco, a Micro$osft mudou demais nesses últimos anos, aquela microsoft que todos os javeiros me alertaram quando eu estava no começo da minha carreira não é tão sombria assim, os caras andam escutando bastante a comunidade, saem muitas releases novas o tempo todo de todas as tecnologias que eles mantem.

Eu comecei a trabalhar com .Net no asp.net mvc 4, já estamos no 5.2 em 1 ano e pouco que eu estou trabalhando com asp.net, existem muitos projetos open-source. Mas voltando ao tópico, concordo um pouco com o post do cara, mas desejo vida longa ao java, se uma ou outra linguagem dominar o mercado em absoluto perdemos a “competitividade” e estaremos fadados a evoluções lentas em questão de novidades, quem sabe não foi isso que aconteceu com o java nos últimos anos…

[quote=ViniGodoy]
Estou me referindo a essa proposta aqui:

Estamos falando da parte de assincronia, não do .Net framework inteiro.[/quote]

Não vejo que relação isso pode ter com aplicações desktops escritas em .net.

A programação assíncrona permite trabalhar com alguns modelos de arquiteturas muito interessantes. Um caso por exemplo é o modelo CQRS de acesso a dados. Ele consiste basicamente em dividir as tarefas de manipulação de modelos de dados em dois conjuntos: Command (atualização / inserção de dados) e Query (leitura de dados). As operações de inserção e atualização na maioria das vezes podem ser feitas assincronamente. Eu não preciso, por exemplo, esperar que uma operação de inserção na base seja concluida para eu continuar o fluxo da minha aplicação. E isso é só um exemplo.
A programação assíncrona no lado backand permite evitar operações bloqueantes desnecessárias. Tudo o que eu não precisar esperar o resultado para continuar o processo da aplicação eu posso mandar fazer assíncronamente.

[quote=matheuslmota]A programação assíncrona permite trabalhar com alguns modelos de arquiteturas muito interessantes. Um caso por exemplo é o modelo CQRS de acesso a dados. Ele consiste basicamente em dividir as tarefas de manipulação de modelos de dados em dois conjuntos: Command (atualização / inserção de dados) e Query (leitura de dados). As operações de inserção e atualização na maioria das vezes podem ser feitas assincronamente. Eu não preciso, por exemplo, esperar que uma operação de inserção na base seja concluida para eu continuar o fluxo da minha aplicação. E isso é só um exemplo.
A programação assíncrona no lado backand permite evitar operações bloqueantes desnecessárias. Tudo o que eu não precisar esperar o resultado para continuar o processo da aplicação eu posso mandar fazer assíncronamente. [/quote]

Sim, teoricamente você poderia enviar um comando como uma operação assíncrona, bem lembrado!

Mas quando o desenvolvedor precisar obter o resultado de uma operação pra prosseguir com o fluxo da aplicação, ainda pode ocorrer o bloqueio.

[code]future = conn.transactAsync(tx);

… // fluxo normal da aplicação

txResult = future.get(); // vai bloquear se tx ainda não estiver concluída (ou abortada)
[/code]

Novamente, a solução neste caso é desenvolvedor que sabe o que esta fazendo, e não funcionalidade X ou Y.

No caso do CQRS (que é um paradigma orientado a dados, e incompatível com objetos) sei que é indicado para cenários com muitas operações de leitura. Não acho que seja uma boa idéia para cenários com muitas operações de escrita, assíncronas ou não, devido as operações serem processadas serialmente no command model.

Eu vejo muito esse argumento usado em listas de discussão C++, para tentar dizer que o garbage collector é inútil… Para mim, esse argumento não faz qualquer sentido. Nós criamos recursos justamente para que os desenvolvedores não precisem se preocupar os mínimos detalhes do que estão fazendo, para evitar que desenvolvedores menos experientes, menos cuidadosos, ou mesmo acidentalmente, cometam erros que a máquina pode evitar.

[quote=lkbm]Mas quando o desenvolvedor precisar obter o resultado de uma operação pra prosseguir com o fluxo da aplicação, ainda pode ocorrer o bloqueio.

[code]future = conn.transactAsync(tx);

… // fluxo normal da aplicação

txResult = future.get(); // vai bloquear se tx ainda não estiver concluída (ou abortada)
[/code][/quote]

Essa seria uma forma errada de trabalhar no paradigma assíncrono. O correto seria você responder a um callback, e deixar o processador fazendo outras coisas que não precisam ser bloqueadas enquanto isso:

//Em C# isso faz com que a thread pare, dando lugar a outras coisas txResult = await conn.transactAsync(tx);

Em JavaScript, com Promises, um código similar seria:

conn.transactAsync(tx).then(function(result) { txResult = result; });

[quote=lkbm]

Mas quando o desenvolvedor precisar obter o resultado de uma operação pra prosseguir com o fluxo da aplicação, ainda pode ocorrer o bloqueio.

[code]future = conn.transactAsync(tx);

… // fluxo normal da aplicação

txResult = future.get(); // vai bloquear se tx ainda não estiver concluída (ou abortada)
[/code]

Novamente, a solução neste caso é desenvolvedor que sabe o que esta fazendo, e não funcionalidade X ou Y.

No caso do CQRS (que é um paradigma orientado a dados, e incompatível com objetos) sei que é indicado para cenários com muitas operações de leitura. Não acho que seja uma boa idéia para cenários com muitas operações de escrita, assíncronas ou não, devido as operações serem processadas serialmente no command model.[/quote]

Mas ai é que tá, você deve usar da assincronia justamente quando você não precisa do resultado da execução. Para operações de alteração / inserção de dados em um banco, por exemplo, esse é o caso adequado em muitas vezes. E incrivelmente isso se adequa até mesmo para operações de leita. Isso mesmo, podemos fazer leitura de dados de forma assíncrona. Onde trabalho estamos desenvolvendo o BackEnd de um sistema usando o paradigma de atores (com o framework akka). Estamos criando uma API de persistência completamente assíncrona. A grande vantagem é que isso vai nos ajudar muito na hora de escalar a nossa aplicação, que tem como grande gargalo hoje o banco de dados. E antes que pergunte, obivamente estamos tendo cuidado para não ter provlemas de inconsistência que podem vir com a assincronia se trabalhada da forma errada.

Só para ilustrar em código funcional o que já conversamos sobre programação assíncrona em C# no backend:

[code]
public async Task ActionRequisicaoExemplo()
{
var t1 = Task.Run(() => ProcessoDemorado1());
var t2 = Task.Run(() => ProcessoDemorado2());

        await Task.WhenAll(t1, t2);

        return "finalizado";
    }

    public static void ProcessoDemorado1()
    {
        Thread.Sleep(10000);
    }

    public static void ProcessoDemorado2()
    {
        Thread.Sleep(10000);
    }

[/code]Como principalmente ViniGodoy falou em um dos posts, o exemplo mostra a execução de dois processos em paralelo. Neste caso, ao invés de durar 20 segundos a execução total, vai durar só 10 a execução dos dois. Existem outras variantes de acordo com a necessidade, mas já dá pra ter noção do quanto está simples programação assíncrona em C#.

[quote=matheuslmota][quote=lkbm]

Mas quando o desenvolvedor precisar obter o resultado de uma operação pra prosseguir com o fluxo da aplicação, ainda pode ocorrer o bloqueio.

[code]future = conn.transactAsync(tx);

… // fluxo normal da aplicação

txResult = future.get(); // vai bloquear se tx ainda não estiver concluída (ou abortada)
[/code]

Novamente, a solução neste caso é desenvolvedor que sabe o que esta fazendo, e não funcionalidade X ou Y.

No caso do CQRS (que é um paradigma orientado a dados, e incompatível com objetos) sei que é indicado para cenários com muitas operações de leitura. Não acho que seja uma boa idéia para cenários com muitas operações de escrita, assíncronas ou não, devido as operações serem processadas serialmente no command model.[/quote]

Mas ai é que tá, você deve usar da assincronia justamente quando você não precisa do resultado da execução. Para operações de alteração / inserção de dados em um banco, por exemplo, esse é o caso adequado em muitas vezes. E incrivelmente isso se adequa até mesmo para operações de leita. Isso mesmo, podemos fazer leitura de dados de forma assíncrona. Onde trabalho estamos desenvolvendo o BackEnd de um sistema usando o paradigma de atores (com o framework akka). Estamos criando uma API de persistência completamente assíncrona. A grande vantagem é que isso vai nos ajudar muito na hora de escalar a nossa aplicação, que tem como grande gargalo hoje o banco de dados. E antes que pergunte, obivamente estamos tendo cuidado para não ter provlemas de inconsistência que podem vir com a assincronia se trabalhada da forma errada. [/quote]

Toda operação envolvendo atores é assíncrona, não importa se leitura ou escrita. É uma característica própria das linguagens que seguem o modelo distribuído de troca de mensagens. Programas C#, Java, C++ seguem um modelo diferente, que eu chamaria de local orientado a objetos.

Não sou muito familiar com o modelo distribuído, mas sei que ele faz sucesso em sistemas… distribuídos… onde os requisitos são bem diferentes dos requisitos esperados para uma aplicação de banco de dados.

Eu vejo muito esse argumento usado em listas de discussão C++, para tentar dizer que o garbage collector é inútil… Para mim, esse argumento não faz qualquer sentido. Nós criamos recursos justamente para que os desenvolvedores não precisem se preocupar os mínimos detalhes do que estão fazendo, para evitar que desenvolvedores menos experientes, menos cuidadosos, ou mesmo acidentalmente, cometam erros que a máquina pode evitar.[/quote]

Em nenhum momento eu disse que operações assíncronas são inúteis.

Apenas disse que se o banco é o gargalo do sistema, tornar as operações com o banco assíncronas não vai fazer o banco ser capaz de processar as requisições mais rápido. Considerando que a maioria dos servidores é capaz de lidar com mais requisições do que o banco, existe a possibilidade de você o sobrecarregar ainda mais o banco dessa maneira.

Sobre garbage collector, meu pensamento é na mesma linha. GC só evita que o desenvolvedor tenha que desalojar o objeto no fim da sua vida. Mas você ainda precisa saber o que esta fazendo e como isso afeta o ciclo de vida dos seus objetos. O preço disso é um processo a mais rodando o gc versus não ter o processo e você desalojar manualmente. Se é útil ou não vai depender de cada caso. Não existe unidade de utilidade universal que funciona pra todo mundo.

[quote=ViniGodoy][quote=lkbm]Mas quando o desenvolvedor precisar obter o resultado de uma operação pra prosseguir com o fluxo da aplicação, ainda pode ocorrer o bloqueio.

[code]future = conn.transactAsync(tx);

… // fluxo normal da aplicação

txResult = future.get(); // vai bloquear se tx ainda não estiver concluída (ou abortada)
[/code][/quote]

Essa seria uma forma errada de trabalhar no paradigma assíncrono. O correto seria você responder a um callback, e deixar o processador fazendo outras coisas que não precisam ser bloqueadas enquanto isso:

//Em C# isso faz com que a thread pare, dando lugar a outras coisas txResult = await conn.transactAsync(tx);

Em JavaScript, com Promises, um código similar seria:

conn.transactAsync(tx).then(function(result) { txResult = result; });

[/quote]

a maneira “correta” vai depender do idioma usado pela linguagem. Em todos os casos o resultado é o mesmo.

Nem falei que você disse. Só estava explicando porque não considero “o programador deve saber o que está fazendo” como um argumento numa discussão sobre funcionalidades de uma linguagem. Um programador que sabe muito jamais precisará de funcionalidade nenhuma que facilite a vide dele “a priori”.

[quote=javaflex]Só para ilustrar em código funcional o que já conversamos sobre programação assíncrona em C# no backend:

[code]
public async Task ActionRequisicaoExemplo()
{
var t1 = Task.Run(() => ProcessoDemorado1());
var t2 = Task.Run(() => ProcessoDemorado2());

        await Task.WhenAll(t1, t2);

        return "finalizado";
    }

    public static void ProcessoDemorado1()
    {
        Thread.Sleep(10000);
    }

    public static void ProcessoDemorado2()
    {
        Thread.Sleep(10000);
    }

[/code]Como principalmente ViniGodoy falou em um dos posts, o exemplo mostra a execução de dois processos em paralelo. Neste caso, ao invés de durar 20 segundos a execução total, vai durar só 10 a execução dos dois. Existem outras variantes de acordo com a necessidade, mas já dá pra ter noção do quanto está simples programação assíncrona em C#.[/quote]

Seu código é funcional no desktop onde um processo demorado pode bloquear a thread do usuário por 10 segundos.

Esse problema não existe na web onde requisições levam ms para processar… não 10 segundos… bom, a não ser que tenha algo errado com o design da sua aplicação web. :open_mouth:

[quote=lkbm][quote=javaflex]Só para ilustrar em código funcional o que já conversamos sobre programação assíncrona em C# no backend:

[code]
public async Task ActionRequisicaoExemplo()
{
var t1 = Task.Run(() => ProcessoDemorado1());
var t2 = Task.Run(() => ProcessoDemorado2());

        await Task.WhenAll(t1, t2);

        return "finalizado";
    }

    public static void ProcessoDemorado1()
    {
        Thread.Sleep(10000);
    }

    public static void ProcessoDemorado2()
    {
        Thread.Sleep(10000);
    }

[/code]Como principalmente ViniGodoy falou em um dos posts, o exemplo mostra a execução de dois processos em paralelo. Neste caso, ao invés de durar 20 segundos a execução total, vai durar só 10 a execução dos dois. Existem outras variantes de acordo com a necessidade, mas já dá pra ter noção do quanto está simples programação assíncrona em C#.[/quote]

Seu código é funcional no desktop onde um processo demorado pode bloquear a thread do usuário por 10 segundos.

Esse problema não existe na web onde requisições levam ms para processar… não 10 segundos… bom, a não ser que tenha algo errado com o design da sua aplicação web. :O[/quote]
Pode ter situações úteis em aplicações de banco de dados. O SGDB é perfeitamente capaz de lidar com diversos acessos ao mesmo tempo, da mesma forma que vários usuários simultâneos. Então pode ser válido se o cenário for favorável e tiver a necessidade.

Trabalho com ASP.NET MVC e tenho situações onde o cliente precisa exportar para Excel relatórios complexos com fonte de dados variadas. Difícil alguém não passar por uma situação de relatório analítico que não demore segundos.