A cross-platform UI framework for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

110 lines
2.9 KiB

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Avalonia.FreeDesktop
{
class DBusCallQueue
{
private readonly Func<Exception, Task> _errorHandler;
class Item
{
public Func<Task> Callback;
public Action<Exception> OnFinish;
}
private Queue<Item> _q = new Queue<Item>();
private bool _processing;
public DBusCallQueue(Func<Exception, Task> errorHandler)
{
_errorHandler = errorHandler;
}
public void Enqueue(Func<Task> cb)
{
_q.Enqueue(new Item
{
Callback = cb
});
Process();
}
public Task EnqueueAsync(Func<Task> cb)
{
var tcs = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
_q.Enqueue(new Item
{
Callback = cb,
OnFinish = e =>
{
if (e == null)
tcs.TrySetResult(0);
else
tcs.TrySetException(e);
}
});
Process();
return tcs.Task;
}
public Task<T> EnqueueAsync<T>(Func<Task<T>> cb)
{
var tcs = new TaskCompletionSource<T>(TaskCreationOptions.RunContinuationsAsynchronously);
_q.Enqueue(new Item
{
Callback = async () =>
{
var res = await cb();
tcs.TrySetResult(res);
},
OnFinish = e =>
{
if (e != null)
tcs.TrySetException(e);
}
});
Process();
return tcs.Task;
}
async void Process()
{
if(_processing)
return;
_processing = true;
try
{
while (_q.Count > 0)
{
var item = _q.Dequeue();
try
{
await item.Callback();
item.OnFinish?.Invoke(null);
}
catch(Exception e)
{
if (item.OnFinish != null)
item.OnFinish(e);
else
await _errorHandler(e);
}
}
}
finally
{
_processing = false;
}
}
public void FailAll()
{
while (_q.Count>0)
{
var item = _q.Dequeue();
item.OnFinish?.Invoke(new OperationCanceledException());
}
}
}
}