#c# #.net #multithreading #c#-2.0
#c# #.net #многопоточность #c #-2.0
Вопрос:
У меня есть код для вызова асинхронных блоков.
private delegate void MyDelegate();
void Async(MyDelegate t) {
Thread thread = new Thread(new ThreadStart(t));
thread.IsBackground = true;
thread.Start();
}
И затем:
Async(delegate() {
// code
});
Я использую его, но я уверен, что это неправильный способ сделать это. В чем проблемы с этим методом?
Комментарии:
1. Предполагая, что вы просто хотите запустить новый поток, который запускает какой-то делегат, это идеальное решение. Почему вы считаете, что это неправильно, и чего вы пытаетесь достичь?
2. Я не уверен, что это неправильно, но это выглядит неубедительно каждый раз, когда я хочу, чтобы что-то не блокировало мой графический интерфейс, чтобы запустить его таким образом. Особенно, если я вызываю его много раз в секунду.
3. @blez: Если вы вызываете это много раз в секунду, вы почти наверняка должны использовать пул потоков.
Ответ №1:
Во-первых, кажется, нет смысла объявлять своего собственного делегата. Почему бы просто не:
void Async(ThreadStart t) {
Thread thread = new Thread(t);
thread.IsBackground = true;
thread.Start();
}
? Лично я не вижу, чтобы я хотел делать это достаточно часто (и без возможности узнать, как продвигается задача), чтобы оправдать отдельный метод. Если вы используете .NET 4, вам следует заглянуть в библиотеку параллельных задач, которая по-прежнему позволяет запускать асинхронные задачи, но более полнофункциональным способом. (РЕДАКТИРОВАТЬ: Хорошо, так что вы не можете использовать это из .NET 2 — это стоит иметь в виду на будущее.)
Вы также можете рассмотреть возможность использования BeginInvoke
метода для делегатов, который позволяет вам в любом случае легко запускать их в пуле потоков и передавать аргументы:
Action<string, int> action = (name, age) => { ... };
IAsyncResult result = action.BeginInvoke("Jon", 35, null);
// Now you can use result if you want...
РЕДАКТИРОВАТЬ: Теперь вы сказали, что будете делать это несколько раз в секунду. Предполагая, что это краткосрочная задача, вы почти наверняка должны использовать для этого пул потоков. Как и в приведенном выше примере, вы также можете использовать ThreadPool.QueueUserWorkItem
его для добавления задачи в пул потоков. Это будет более эффективно (за счет повторного использования потока), чем создавать новый поток каждый раз, когда у вас есть задача.
Комментарии:
1. Я использую его для тяжелых задач и для многих небольших задач (например, 100 звонков в секунду). Всегда ли использование пула потоков является лучшим вариантом? Я не использовал Action, это третий способ вызова асинхронного кода?
2. @blez:
Action<,>
это всего лишь примерный тип делегата (на самом деле из .NET 3.5, но это всего лишь тип делегата — очевидно, вы можете объявить свой собственный). У всех делегатов естьBeginInvoke
методы. Вы обязательно должны использовать пул потоков для краткосрочных задач. Те, что работают дольше, могли бы разумно использовать отдельные потоки.
Ответ №2:
Поскольку у вас уже есть делегат
private delegate void MyDelegate();
вы можете сделать это
new MyDelegate(delegate
{
// code
}).BeginInvoke(null, null);
Он будет использовать потоки пула потоков, чтобы вы не перегружали время выполнения слишком большим количеством потоков.