Сообщение Re: SynchronizationContext a-la node.js от 30.09.2016 9:10
Изменено 30.09.2016 9:13 Serginio1
Здравствуйте, SuhanovSergey, Вы писали:
SS>Хочется иметь SynchronizationContext
SS>- который бы сериализовал колбэки, так что только один колбэк испольняется в момент времени
SS>- не являлся бю UI-ным SynchronizationContext-ом, а испльзовал бы тред пул. Никакой тред не должен спать, ожидая колбэков.
SS>Нужно для IO-bound фоновый задачи, которая запускает параллельные составные IO таски и не хочет синзронизировать доступ к общим переменным между await-ами.
Может я не понял вопроса, но вот здесь Consuming the Task-based Asynchronous Pattern
Есть пример асинхронной очереди
Используя эту структуру данных, можно написать следующий код:
SS>Хочется иметь SynchronizationContext
SS>- который бы сериализовал колбэки, так что только один колбэк испольняется в момент времени
SS>- не являлся бю UI-ным SynchronizationContext-ом, а испльзовал бы тред пул. Никакой тред не должен спать, ожидая колбэков.
SS>Нужно для IO-bound фоновый задачи, которая запускает параллельные составные IO таски и не хочет синзронизировать доступ к общим переменным между await-ами.
Может я не понял вопроса, но вот здесь Consuming the Task-based Asynchronous Pattern
Есть пример асинхронной очереди
public class AsyncProducerConsumerCollection<T>
{
private readonly Queue<T> m_collection = new Queue<T>();
private readonly Queue<TaskCompletionSource<T>> m_waiting =
new Queue<TaskCompletionSource<T>>();
public void Add(T item)
{
TaskCompletionSource<T> tcs = null;
lock (m_collection)
{
if (m_waiting.Count > 0) tcs = m_waiting.Dequeue();
else m_collection.Enqueue(item);
}
if (tcs != null) tcs.TrySetResult(item);
}
public Task<T> Take()
{
lock (m_collection)
{
if (m_collection.Count > 0)
{
return Task.FromResult(m_collection.Dequeue());
}
else
{
var tcs = new TaskCompletionSource<T>();
m_waiting.Enqueue(tcs);
return tcs.Task;
}
}
}
}
Используя эту структуру данных, можно написать следующий код:
private static AsyncProducerConsumerCollection<int> m_data = …;
…
private static async Task ConsumerAsync()
{
while(true)
{
int nextItem = await m_data.Take();
ProcessNextItem(nextItem);
}
}
…
private static void Produce(int data)
{
m_data.Add(data);
}
Re: SynchronizationContext a-la node.js
Здравствуйте, SuhanovSergey, Вы писали:
SS>Хочется иметь SynchronizationContext
SS>- который бы сериализовал колбэки, так что только один колбэк испольняется в момент времени
SS>- не являлся бю UI-ным SynchronizationContext-ом, а испльзовал бы тред пул. Никакой тред не должен спать, ожидая колбэков.
SS>Нужно для IO-bound фоновый задачи, которая запускает параллельные составные IO таски и не хочет синзронизировать доступ к общим переменным между await-ами.
Может я не понял вопроса, но вот здесь Consuming the Task-based Asynchronous Pattern
Есть пример асинхронной очереди
Используя эту структуру данных, можно написать следующий код:
Там же
Пространство имен System.Threading.Tasks.Dataflow включает тип BufferBlock<T>, который можно использовать таким же образом, но без построения пользовательского типа коллекции:
SS>Хочется иметь SynchronizationContext
SS>- который бы сериализовал колбэки, так что только один колбэк испольняется в момент времени
SS>- не являлся бю UI-ным SynchronizationContext-ом, а испльзовал бы тред пул. Никакой тред не должен спать, ожидая колбэков.
SS>Нужно для IO-bound фоновый задачи, которая запускает параллельные составные IO таски и не хочет синзронизировать доступ к общим переменным между await-ами.
Может я не понял вопроса, но вот здесь Consuming the Task-based Asynchronous Pattern
Есть пример асинхронной очереди
public class AsyncProducerConsumerCollection<T>
{
private readonly Queue<T> m_collection = new Queue<T>();
private readonly Queue<TaskCompletionSource<T>> m_waiting =
new Queue<TaskCompletionSource<T>>();
public void Add(T item)
{
TaskCompletionSource<T> tcs = null;
lock (m_collection)
{
if (m_waiting.Count > 0) tcs = m_waiting.Dequeue();
else m_collection.Enqueue(item);
}
if (tcs != null) tcs.TrySetResult(item);
}
public Task<T> Take()
{
lock (m_collection)
{
if (m_collection.Count > 0)
{
return Task.FromResult(m_collection.Dequeue());
}
else
{
var tcs = new TaskCompletionSource<T>();
m_waiting.Enqueue(tcs);
return tcs.Task;
}
}
}
}
Используя эту структуру данных, можно написать следующий код:
private static AsyncProducerConsumerCollection<int> m_data = …;
…
private static async Task ConsumerAsync()
{
while(true)
{
int nextItem = await m_data.Take();
ProcessNextItem(nextItem);
}
}
…
private static void Produce(int data)
{
m_data.Add(data);
}
Там же
Пространство имен System.Threading.Tasks.Dataflow включает тип BufferBlock<T>, который можно использовать таким же образом, но без построения пользовательского типа коллекции:
private static BufferBlock<int> m_data = …;
…
private static async Task ConsumerAsync()
{
while(true)
{
int nextItem = await m_data.ReceiveAsync();
ProcessNextItem(nextItem);
}
}
…
private static void Produce(int data)
{
m_data.Post(data);
}