Skip to content

Instantly share code, notes, and snippets.

@jpolvora
Last active July 24, 2017 13:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jpolvora/4688843 to your computer and use it in GitHub Desktop.
Save jpolvora/4688843 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
namespace AsyncKonsole
{
class Program
{
const bool UsuarioLogado = true;
const string Permissoes = "administrador,operador";
//const string Permissoes = "";
public static void Main(string[] args)
{
//inicia a execução da co-rotina
Coroutine.BeginExecute(Workflow());
//console aguarda execução da rotina
Console.ReadLine();
}
static void CallWebService() {
//simula consulta ao webservice (3 segundos)
Thread.Sleep(3000);
}
static IEnumerable<Promise> Workflow() {
//cria o objeto "promise" construído com uma Func que retorna uma instância de um "future"
var step1 = new Promise<bool>(VerificaUsuarioLogado);
//o enumerador da co-rotina "starta" o delegate referenciado pelo promise, e aguarda sua finalização
yield return step1;
//quando algum valor for setado na instância do "future" contido no "promise", o enumerador avança
//e esta linha é executada, assim podemos ler o valor retornado (bool)
if (step1.Current.Value)
Console.WriteLine("Usuário está logado.");
else {
Console.WriteLine("Usuário não está logado. Fim da rotina.");
yield break; //termina a execução da co-rotina
}
//dessa vez crio uma promise em que o valor esperado é um array de strings
var step2 = new Promise<string[]>(RecuperaPermissoes);
yield return step2;
var permissoes = step2.Current.Value;
foreach (var permissao in permissoes) {
Console.WriteLine(permissao);
}
if (permissoes.Length == 0) {
Console.WriteLine("Sem permissões!");
var step3 = new Promise<object>(MostraTelaLogin);
yield return step3;
yield break; //sai da rotina.
}
else Console.WriteLine("Permissões concedidas");
}
static Future<bool> VerificaUsuarioLogado() {
var future = new Future<bool>();
var task = new Task(CallWebService);
task.ContinueWith(x => {
future.Value = UsuarioLogado; //quando o valor é setado, o enumerador avança
});
task.Start();
return future;
}
static Future<object> MostraTelaLogin() {
var future = new Future<object>();
var task = Task.Factory.StartNew(() => Console.WriteLine("Bem vindo a tela de login"))
.ContinueWith(x => future.Value = null);
return future;
}
static Future<string[]> RecuperaPermissoes() {
var future = new Future<string[]>();
var task = new Task(CallWebService);
task.ContinueWith(x => {
var permissoes = Permissoes.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries);
future.Value = permissoes;
});
task.Start();
return future;
}
}
}
public static class Coroutine {
public static void BeginExecute(IEnumerable<Promise> enumerable) {
MoveNext(enumerable.GetEnumerator());
}
static void MoveNext(IEnumerator<Promise> enumerator) {
if (enumerator.MoveNext()) {
var promise = enumerator.Current;
promise.Current = promise.Task();
promise.Current._CallBack = () => MoveNext(enumerator);
} else {
enumerator.Dispose();
}
}
}
public abstract class Future {
private object _value;
public object Value {
get { return _value;}
set { _value = value;
Now();
}
}
void Now() {
if (_CallBack == null) throw new InvalidOperationException("_CallBack não foi definido pelo Enumerador");
_CallBack();
}
/// <summary>
/// The Coroutine enumerator internally sets this Property to a delegate that points
/// to its continuation delegate, so it can moveNext() the enumerator
/// </summary>
internal Action _CallBack { get; set; }
}
public class Future<T> : Future {
public new T Value {
get { return (T)base.Value; }
set { base.Value = value; }
}
}
public abstract class Promise {
public Future Current { get; internal set; }
internal Func<Future> Task { get; private set; }
protected Promise(Func<Future> task) {
Task = task;
}
}
public class Promise<T> : Promise {
public new Future<T> Current {
get { return (Future<T>)base.Current; }
internal set { base.Current = value; }
}
public Promise(Func<Future<T>> task)
: base(() => task()) {
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment