Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C#/NETC内核中的临时服务实例之间共享线程安全字段?_C#_Multithreading_Asp.net Core_.net Core_Thread Safety - Fatal编程技术网

在C#/NETC内核中的临时服务实例之间共享线程安全字段?

在C#/NETC内核中的临时服务实例之间共享线程安全字段?,c#,multithreading,asp.net-core,.net-core,thread-safety,C#,Multithreading,Asp.net Core,.net Core,Thread Safety,我需要在从.NETCore中的临时服务调用的函数之间共享一些锁(也称为“对象”字段)和常规数据字段。 当然,这些锁和字段应该以线程安全的方式声明 最好的方法是什么?我正在考虑单独的单身服务。我是否必须向声明的字段和锁添加一些关键字,以使它们是线程安全的 我非常熟悉Java多线程,但到目前为止还没有在C#中使用过。这是我能想到的最简单的例子。它使用。您也可以使用。基本上,我解决了一个临时服务3次。然后启动两个线程,这将增加共享服务的价值 class Program { static asy

我需要在从.NETCore中的临时服务调用的函数之间共享一些锁(也称为“对象”字段)和常规数据字段。 当然,这些锁和字段应该以线程安全的方式声明

最好的方法是什么?我正在考虑单独的单身服务。我是否必须向声明的字段和锁添加一些关键字,以使它们是线程安全的


我非常熟悉Java多线程,但到目前为止还没有在C#中使用过。

这是我能想到的最简单的例子。它使用。您也可以使用。基本上,我解决了一个临时服务3次。然后启动两个线程,这将增加共享服务的价值

class Program
{
    static async Task Main(string[] args)
    {
        var serviceCollection = new ServiceCollection();
        serviceCollection.AddSingleton<ValueService>();
        serviceCollection.AddTransient<Service>();
        var provider = serviceCollection.BuildServiceProvider();

        var serviceOne = provider.GetRequiredService<Service>();
        var serviceTwo = provider.GetRequiredService<Service>();
        var serviceThree = provider.GetRequiredService<Service>();

        // Manipulate the same object 1500 times, from different threads.
        var task1 = serviceOne.DoStuff(500);
        var task2 = serviceTwo.DoStuff(500);
        var task3 = serviceThree.DoStuff(500);

        // Wait for all the threads to complete.
        await Task.WhenAll(task1, task2, task3);

        // Verify the result.
        var valueService = provider.GetRequiredService<ValueService>();
        Console.WriteLine(valueService.SomeValue);
        Console.ReadKey();
    }
}

internal class Service
{
    private readonly ValueService _service;

    public Service(ValueService service)
    {
        _service = service;
    }

    public Task DoStuff(int noOfTimes)
    {
        var tasks = new Task[noOfTimes];

        for (int i = 0; i < noOfTimes; i++)
        {
            tasks[i] = Task.Run(() =>
            {
                Thread.Sleep(100);
                _service.Increase();
            });
        }

        return Task.WhenAll(tasks);
    }

}

internal class ValueService
{
    public void Increase()
    {
        // Use lock to make sure that only one thread is changing the field at the time.
        // Remove the lock statement and you will notice some "unwanted" behaviour.
        lock (_lock) 
        {
            SomeValue++;
        }

        // Alternatively you can use Interlocked.Increment(SomeValue)
    }

    private readonly object _lock = new object();
    public int SomeValue { get; private set; }
}
类程序
{
静态异步任务主(字符串[]args)
{
var servicecolection=新servicecolection();
serviceCollection.AddSingleton();
serviceCollection.AddTransient();
var provider=serviceCollection.BuildServiceProvider();
var serviceOne=provider.GetRequiredService();
var serviceTwo=provider.GetRequiredService();
var servicetree=provider.GetRequiredService();
//从不同线程操作同一对象1500次。
var task1=serviceOne.DoStuff(500);
var task2=service2.DoStuff(500);
var task3=servicetree.DoStuff(500);
//等待所有线程完成。
等待任务。WhenAll(任务1、任务2、任务3);
//验证结果。
var valueService=provider.GetRequiredService();
Console.WriteLine(valueService.SomeValue);
Console.ReadKey();
}
}
内部班级服务
{
私有只读ValueService \u服务;
公共服务(价值服务)
{
_服务=服务;
}
公共任务DoStuff(中午时分)
{
var tasks=新任务[中午];
for(int i=0;i
{
睡眠(100);
_服务增加();
});
}
返回任务。WhenAll(任务);
}
}
内部类价值服务
{
公共空间增加()
{
//使用lock确保一次只有一个线程在更改字段。
//删除lock语句,您将注意到一些“不想要的”行为。
锁
{
SomeValue++;
}
//或者,您可以使用Interlocked.Increment(SomeValue)
}
私有只读对象_lock=新对象();
public int SomeValue{get;private set;}
}

对于线程安全处理,您可以查看
监视器
锁定
-因为ValueService是一个单例,您不需要将_lock字段标记为静态。所有线程将使用相同的值,因为它是一个singleton@RichardBlewett是的,确实如此。我已经更新了示例。非常感谢。您是否可以评论一下:“get”操作线程是否一致,在这种情况下(因此,如果我尝试设置,get将获得其他线程正在设置的内容?),以及为什么没有使用
volatile
?@AskarIbragimov
volatile
可以使用,但它不会替换
lock
。关于volatile我建议你重新开始。当前,
get
不是线程安全的,因为它可能返回另一个线程正在写入的值。你可能也想锁定它。您可以在
get
set
中使用相同的
lock
。在这种情况下,您可能应该修改示例以包括读取时锁定。