Информация об изменениях

Сообщение Re[33]: Можно ли избавиться от async|await? от 19.12.2025 16:46

Изменено 19.12.2025 16:54 Serginio1

Re[33]: Можно ли избавиться от async|await?
Здравствуйте, ·, Вы писали:


S>>·>Какие конкретно камни ты имеешь в виду и как они обходятся в c#?

·>ИЧСХ, ответа не последовало.
Я тебе уже приводил статью, там все расписано.

S>>·>Так ради чего создавать лишнюю сложность в виде копипасты Thread.Sleep/Task.Delay и т.п., чтобы потом пришлось отважно бороться ИИями? В чём ценность сего действа?

S>>·>А просто решать сами бизнес-задачи (хоть с ИИ, хоть без) — не солидно что-ли?
S>>В том, что бы перенести старый код. Только и всего.
·>Т.е. самоцель. Ценность переписывания кода — перенести старый код. Круто, чё. Хобби у тебя, видимо, такое: переписывание кода из пустого в порожнее.

Не самоцель, а необходимость переноса старого кода, для увеличения производительности серверов.

S>>·>Затем, что код с потоками проще, даже если понадобится высокая производительность и много пользователей.

S>>Так и с тасками он не особо то и сложный. Учитывая разного рода Task.WhenAll, Task.WhenAny, CancellationToken
·>Ок, т.е. ты соглашаешься, что код с потоками проще. Надеюсь, ты получил ответ на свой вопрос.
Я соглашаюсь, что он проще, но и примитивнее. Бейсик тоже простой, только вот много на нем не сделаешь.
С Задачами у тебя намного больше свободы. Кроме того есть прекрасная вещь как TaskCompletionSource.
Пример

AsyncProducerConsumerCollection

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);
}



Кроме того и от блокировок можно избавляться

// БЫЛО
public class DataProcessor
{
    private ThreadLocal<List<int>> cache = new();
    private object syncRoot = new();
    
    public void Process()
    {
        lock(syncRoot)
        {
            Thread.Sleep(1000);
            // обработка
        }
    }
}

// СТАЛО
public class DataProcessor
{
    private AsyncLocal<List<int>> cache = new();
    private SemaphoreSlim semaphore = new(1, 1);
    
    public async Task ProcessAsync(CancellationToken ct = default)
    {
        await semaphore.WaitAsync(ct);
        try
        {
            await Task.Delay(1000, ct);
            // асинхронная обработка
        }
        finally
        {
            semaphore.Release();
        }
    }
}
Re[33]: Можно ли избавиться от async|await?
Здравствуйте, ·, Вы писали:


S>>·>Какие конкретно камни ты имеешь в виду и как они обходятся в c#?

·>ИЧСХ, ответа не последовало.
Я тебе уже приводил статью, там все расписано.

S>>·>Так ради чего создавать лишнюю сложность в виде копипасты Thread.Sleep/Task.Delay и т.п., чтобы потом пришлось отважно бороться ИИями? В чём ценность сего действа?

S>>·>А просто решать сами бизнес-задачи (хоть с ИИ, хоть без) — не солидно что-ли?
S>>В том, что бы перенести старый код. Только и всего.
·>Т.е. самоцель. Ценность переписывания кода — перенести старый код. Круто, чё. Хобби у тебя, видимо, такое: переписывание кода из пустого в порожнее.

Не самоцель, а необходимость переноса старого кода, для увеличения производительности серверов.

S>>·>Затем, что код с потоками проще, даже если понадобится высокая производительность и много пользователей.

S>>Так и с тасками он не особо то и сложный. Учитывая разного рода Task.WhenAll, Task.WhenAny, CancellationToken
·>Ок, т.е. ты соглашаешься, что код с потоками проще. Надеюсь, ты получил ответ на свой вопрос.
Я соглашаюсь, что он проще, но и примитивнее. Бейсик тоже простой, только вот много на нем не сделаешь.
Многие тоже по началу воротили нос от задач с async/await
С Задачами у тебя намного больше свободы. Кроме того есть прекрасная вещь как TaskCompletionSource c которым ты сам можешь контролировать задачу.
Пример

AsyncProducerConsumerCollection

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);
}



Кроме того и от блокировок можно избавляться

// БЫЛО
public class DataProcessor
{
    private ThreadLocal<List<int>> cache = new();
    private object syncRoot = new();
    
    public void Process()
    {
        lock(syncRoot)
        {
            Thread.Sleep(1000);
            // обработка
        }
    }
}

// СТАЛО
public class DataProcessor
{
    private AsyncLocal<List<int>> cache = new();
    private SemaphoreSlim semaphore = new(1, 1);
    
    public async Task ProcessAsync(CancellationToken ct = default)
    {
        await semaphore.WaitAsync(ct);
        try
        {
            await Task.Delay(1000, ct);
            // асинхронная обработка
        }
        finally
        {
            semaphore.Release();
        }
    }
}