Личный список потока, но разделенный с методами
Мне нужно запустить несколько потоков, но каждый поток будет иметь свой список. Это означает, что списки не должны быть общими, но доступ к ним будет осуществляться разными способами.
class foo()
{
//put the list definition here as a property?
public main()
{
launchthread(threadMethod1)
}
public void threadMethod1()
{
// create a list instance here?
// do something about the list, modify data in it
threadMethod2();
}
public void threadMethod2()
{
// do something about list, modify data in it
}
}
Как правильно определить список, куда поместить определение? и имеет ли это какое-либо отношение к потокобезопасным, если я хочу только частный список потока?
Я ищу варианты, кроме передачи списка в качестве параметра для threadmethod2
,
Предполагая, что мне не нужно использовать ConcurrentBag/SynchronizedCollection
или беспокоиться о замке?
2 ответа
Я прав, что вы готовы начать свои темы примерно так:
class Foo<T>()
{
List<T> TLS;
public main()
{
launchThread(threadMethod1)
}
public void threadMethod1()
{
TLS = new List<T>()
// TLS.Add(); HERE
threadMethod2();
}
public void threadMethod2()
{
// TLS.Add(); HERE
}
}
Если это так, то это полностью потокобезопасно для вас, и вам не нужно ConcurrentCollection
-класс в вашем foo
определение, так как есть только один поток, который будет обращаться к этой переменной. Вам не нужно добавлять список в качестве параметра, так как либо threadMethod1
или же threadMethod2
должны быть экземплярами-методами, и код внутри них будет видеть ту же ссылку TLS
переменная.
Я хочу отметить, что вы не используете стандартные стандарты кодирования для C# - например, имена классов и методов отсутствуют в CamelCasing. Я думаю, что ваш код должен быть правильно отформатирован.
Также хочу отметить, что threadMethod1
или же threadMethod2
не должно быть public
так как они вызываются только из класса, и вы должны запретить другим классам использовать их (если я хорошо понимаю вашу архитектуру).
Хорошая ссылка о TLS
(thread-local-storage) из комментариев.
Я хотел бы обратить внимание на несколько моментов: разработка многопоточного решения.
Главный поток необходим на случай, если в будущем понадобится обработчик потоков, например, для мониторинга состояния потока. Ниже основной основной поток.
public MasterThread
{
private ConcurrentBag<MyThreadImplementation> threadList;
public MasterThread()
{
threadList = new ConcurrentBag<MyThreadImplementation>();
}
public void LaunchThread(MyThreadImplementation newThread)
{
threadList.Add(newThread);
newThread.Start();
}
}
Обратите внимание, что MyThreadImplementation будет межфазным или абстрактным классом, который определяет общие методы всех потоков, которые вы хотите реализовать, или класс Thread, если вам не нужна конкретная реализация или логика в ваших потоках. Я хотел бы предложить абстрактный класс ниже
public abstract class MyThreadImplememtation : Thread
{
private List<YourObject> privateList;
public MyThreadImplementation()
{
list = new ArrayList<MyObject>();
}
// it will be executed when Thread.start() is called
public void run()
{
CommonMethod();
ConcreteMethod();
}
public void CommonMethod()
{
// common method to all threads, it can manipulate the private list
}
// abstract method to be implemented by the children clases
public abstract void ConcreteMethod();
}
Обратите внимание, что все ваши потоки будут наследоваться от MyThreadImplementation и реализовывать свою собственную логику, каждый из которых будет иметь свой собственный закрытый список и свою собственную логику, за исключением CommonMethod, который будет одинаковым для всех потоков. Также основная логика потоков будет запускаться сначала CommonMethod, а затем ConcreteMethod.
Пример потока:
public class WhateverThread : MyThreadImplementation
{
public override void ConcreteMethod()
{
// manipulate the private list
list.Add(new YourObject());
}
}