相关疑难解决方法(0)

ConcurrentBag的正确用法是什么?

我已经在这里阅读过以前的问题,ConcurrentBag但没有找到多线程实现的实际示例.

ConcurrentBag是一个线程安全的包实现,针对同一个线程生成和使用存储在包中的数据的情况进行了优化.

目前这是我的代码中的当前用法(这是简化而非实际代码):

private void MyMethod()
{
    List<Product> products = GetAllProducts(); // Get list of products
    ConcurrentBag<Product> myBag = new ConcurrentBag<Product>();

    //products were simply added here in the ConcurrentBag to simplify the code
    //actual code process each product before adding in the bag
    Parallel.ForEach(
                products,
                new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount },
                product => myBag.Add(product));

    ProcessBag(myBag); // method to process each items in the concurrentbag
}
Run Code Online (Sandbox Code Playgroud)

我的问题:
这是正确的用法ConcurrentBag吗?ConcurrentBag在这种情况下可以使用吗?

对我来说,我认为一个简单List<Product>的手动锁会做得更好.这样做的原因是上面的场景已经打破了" 同一个线程将生成和消费存储在包中的数据 "规则.
另外我还发现 …

c# concurrency multithreading

50
推荐指数
2
解决办法
4万
查看次数


记忆障碍发生器

阅读Joseph Albahari的线程教程,以下内容被提及为内存障碍的生成器:

  • C#的lock陈述(Monitor.Enter/ Monitor.Exit)
  • Interlocked班上的所有方法
  • 使用线程池的异步回调 - 包括异步委托,APM回调和任务延续
  • 设置和等待信令构造
  • 任何依赖于信令的东西,例如启动或等待任务

此外,Hans Passant和Brian Gideon 补充了以下内容(假设其中没有一个已经符合以前的类别之一):

  • 启动或唤醒线程
  • 上下文切换
  • Thread.Sleep()

我想知道这个清单是否完整(如果完整清单甚至可以实际制作)

编辑补充建议:

  • 易失性(读数意味着获取围栏,写作意味着释放围栏)

c# memory-barriers

24
推荐指数
2
解决办法
4193
查看次数

什么线程在`await`关键字后运行代码?

让我发一个简单的例子:

    private void MyMethod()
    {
        Task task = MyAsyncMethod();
        task.Wait();
    }

    private async Task MyAsyncMethod()
    {
        //Code before await
        await MyOtherAsyncMethod();
        //Code after await
    }
Run Code Online (Sandbox Code Playgroud)

假设我在一个单线程应用程序中运行上面的代码 - 就像一个控制台应用程序 - .我很难理解代码//Code after await是如何运行的.

我明白当我awaitMyAsyncMethod()控制中点击关键字时会回到原点MyMethod(),但后来我将锁定该线程task.Wait().如果线程被锁定,//Code after await如果应该接受它的线程被锁定,怎么能运行?

是否创建了一个新线程来运行//Code after await?或者主线程神奇地走出task.Wait()去运行//Code after await

我不确定这是怎么回事?

c# multithreading asynchronous async-await

8
推荐指数
2
解决办法
3203
查看次数

异步代码,共享变量,线程池线程和线程安全

当我使用async / await编写异步代码时,通常是ConfigureAwait(false)为了避免捕获上下文,我的代码正在从一个线程池线程跳转到每个线程池之后await。这引起了对线程安全性的担忧。此代码安全吗?

static async Task Main()
{
    int count = 0;
    for (int i = 0; i < 1_000_000; i++)
    {
        Interlocked.Increment(ref count);
        await Task.Yield();
    }
    Console.WriteLine(count == 1_000_000 ? "OK" : "Error");
}
Run Code Online (Sandbox Code Playgroud)

该变量i不受保护,可以由多个线程池线程访问*。尽管访问模式是非并行的,但是从理论上讲,每个线程都应该可以将的本地缓存值递增i,从而导致超过1,000,000次迭代。我实际上无法产生这种情况。上面的代码在我的机器上始终可以正常打印。这是否意味着代码是线程安全的?或者我应该i使用lock?同步对变量的访问?

(*根据我的测试,平均每2次迭代发生一次线程切换)

c# thread-safety threadpool async-await

8
推荐指数
1
解决办法
246
查看次数

Parallel.ForEach同时保留订单

我有一个List<byte[]>,我喜欢将每个反序列byte[]化为Foo.列表是有序的,我喜欢写一个并行循环,其中结果List<Foo>包含所有Foo的顺序与原始顺序相同byte[].该列表非常大,可以使并行操作变得有价值.有没有内置的方法来实现这一目标?

如果没有,任何想法如何实现同步运行这一切的加速?

谢谢

c# collections parallel-processing concurrency asynchronous

7
推荐指数
1
解决办法
5417
查看次数

多个Parallel.ForEach调用,MemoryBarrier?

我有一堆数据行,我想使用Parallel.ForEach来计算每一行的某些值,就像这样......

class DataRow
{
    public double A { get; internal set; }
    public double B { get; internal set; }
    public double C { get; internal set; }

    public DataRow()
    {
        A = double.NaN;
        B = double.NaN;
        C = double.NaN;
    }
}

class Program
{
    static void ParallelForEachToyExample()
    {
        var rnd = new Random();
        var df = new List<DataRow>();

        for (int i = 0; i < 10000000; i++)
        {
            var dr = new DataRow {A = rnd.NextDouble()};
            df.Add(dr);
        }

        // …
Run Code Online (Sandbox Code Playgroud)

c# multithreading task-parallel-library parallel.foreach

5
推荐指数
1
解决办法
1118
查看次数

异步 LINQ - 不懒?多线程?

我有以下代码:

var things = await GetDataFromApi(cancellationToken);

var builder = new StringBuilder(JsonSerializer.Serialize(things));

await things
    .GroupBy(x => x.Category)
    .ToAsyncEnumerable()
    .SelectManyAwaitWithCancellation(async (category, ct) =>
    {
        var thingsWithColors = await _colorsApiClient.GetColorsFor(category.Select(thing => thing.Name).ToList(), ct);
        
        return category
            .Select(thing => ChooseBestColor(thingsWithColors))
            .ToAsyncEnumerable();
    })
    .ForEachAsync(thingAndColor =>
    {
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId); // prints different IDs
        builder.Replace(thingAndColor.Thing, $"{thingAndColor.Color} {thingAndColor.Thing}");
    }, cancellationToken);
Run Code Online (Sandbox Code Playgroud)

它使用System.Linq.Async并且我发现很难理解。ToList()在“经典”/同步 LINQ 中,只有当我调用或ToArray()使用它时,整个事情才会执行。在上面的示例中,没有此类调用,但 lambda 无论如何都会执行。它是如何工作的?

我的另一个担忧是关于多线程。我多次听说异步!=多线程。那么,怎么可能打印Console.WriteLine(Thread.CurrentThread.ManagedThreadId);出各种ID呢?有些 ID 会被打印多次,但输出中总共有大约 5 个线程 ID。我的代码都没有显式创建任何线程。这都是异步等待。不StringBuilder支持多线程,我想了解上面的实现是否有效。

请忽略我代码的算法,这并不重要,这只是一个例子。重要的是 System.Async.Linq 的使用。

c# linq multithreading asynchronous async-await

3
推荐指数
1
解决办法
292
查看次数

在任何情况下,异步等待方法中的对象更改是否在完成后可见?

在任何情况下,异步/等待方法中的对象更改在完成后是否可见?

经过大量调查后,我仍然无法找到明确的声明,如果在任何情况下完成 await 后,从异步等待方法内部对外部对象所做的更新是否对正在进行的代码可见。

代码示例是某种过滤器链,其中每个过滤器都应该看到先前过滤器所做的任何更改。之后,相同的对象将用于进一步处理。

过滤器不会并行执行。除此之外,由于性能原因,我不想克隆对象。

请参阅以下代码示例:

class Program
{
    private List<ICallback> _allCallbacks = new List<ICallback>();

    public Program()
    {
        // Setup callbacks, perhaps by dependency injection
        _allCallbacks.Add(new MyCallback1());
        _allCallbacks.Add(new MyCallback2());
    }

    static async Task Main()
    {
        Program p = new Program();
        await p.RunBusinessLogic();
        Console.ReadLine();
    }

    private async Task RunBusinessLogic()
    {
        MyDto dto = new MyDto();

        // Setting initial value
        dto.TestProperty = "start";

        // Execute all callbacks and await completion
        await ExecuteCallbacks(dto).ConfigureAwait(false);

        // *** Is dto.TestProperty always guaranteed to …
Run Code Online (Sandbox Code Playgroud)

.net c# memory-model async-await .net-core

2
推荐指数
1
解决办法
218
查看次数