Тайм-аут потока в c#

Я плохо знаком с поточной обработкой в C#. Имеет ли так или иначе установку тайм-аута для потока, не блокируя вызывающий поток (в C# 3.5)?

В противном случае действительно ли логично выполнить функцию с помощью потока, и в той функции создают поток и присоединяются к нему для преодоления этой основной проблемы блокирования потока? Проиллюстрировать:

Вместо:

Public void main()
{
        ...
        Thread thrd1 = new Thread(new ThreadStart(targetObj.targetFunc));
        thrd1.Start();
        thrd1.Join();
        ...
}

Используя что-то как:

Public void main()
{
        ...
        Thread thrd1 = new Thread(new ThreadStart(middleObj.waiter));
        thrd1.Start();
        ...
}

//And in the middleObj.waiter():
Public void waiter()
{
        Thread thrd2 = new Thread(new ThreadStart(targetObj.targetFunc));
        thrd2.Start();
        thrd2.Join();
}
8
задан Kiquenet 12 April 2013 в 07:23
поделиться

6 ответов

Возможно, вы также захотите взглянуть на ThreadPool.QueueUserWorkItem() ( http://msdn.microsoft.com/en-us/library/kbf0f1ct.aspx ), который делает многое за вас.

Как заметил Брайан, прерывание потока обычно не является разумным действием, поскольку в этот момент он может быть занят какими-то важными делами.

1
ответ дан 5 December 2019 в 21:15
поделиться
0
ответ дан 5 December 2019 в 21:15
поделиться

Проще всего вызвать Thread.Join в безопасных точках из основного потока и передать время, в течение которого вы хотите дождаться соединения.

public static void Main()
{
  TimeSpan timeout = TimeSpan.FromSeconds(30);
  Thread thread = new Thread(() => { ThreadMethod(); });
  thread.Start();
  DateTime timeStarted = DateTime.UtcNow;
  DoSomeWorkOnThisThread();
  // We are at a safe point now so check the thread status.
  TimeSpan span = DateTime.UtcNow - timeStarted; // How long has the thread been running.
  TimeSpan wait = timeout - span; // How much more time should we wait.
  if (!thread.Join(wait))
  {
    thread.Abort(); // This is an unsafe operation so use as a last resort.
  }
}
0
ответ дан 5 December 2019 в 21:15
поделиться

«Присоединиться к члену -> Блокирует вызывающий поток, пока поток не завершится, продолжая выполнять стандартную перекачку COM и SendMessage». Сайт MSDN.

thrd1.Join () указывает вызывающему потоку дождаться завершения thrd1.

Мое любимое решение - создать небольшой класс, который мог бы контролировать выполнение потока.

public class MyClass
    {
        private bool _stop;
        private Thread _myThread;

        public void Stop()
        {
            _stop = true;
            //Will block the calling thread until the thread die
            _myThread.Join();
        }

        public void Run()
        {
            _stop = false;
            _myThread = new Thread(Work);
        }

        public void Work()
        {
            do
            {

            } while (!_stop);
        }
   }
0
ответ дан 5 December 2019 в 21:15
поделиться

Посмотрите на метод WaitHandle.WaitOne() со схемой middleObject.

Public void main()
{
    ...
    middleObj.WaitHandle.Reset();
    Thread thrd1 = new Thread(new ThreadStart(middleObj.waiter));
    thrd1.Start();
    middleObj.WaitHandle.WaitOne(timeout);
    ...
}


//And in the middleObj.waiter():
Public void waiter()
{
    Thread thrd2 = new Thread(new ThreadStart(targetObj.targetFunc));
    thrd2.Start();
    thrd2.Join();
    this.WaitHandle.Set();
}

Хотя не уверен, что произойдет с незавершенным потоком.

0
ответ дан 5 December 2019 в 21:15
поделиться

Вы можете запустить System.Threading.Timer для каждого потока и передать ему ManagedThreadId потока. Храните словари для активных потоков и их таймеров с ключом ManagedThreadId. Если таймер истекает, используйте переданный идентификатор потока, чтобы прервать поток и убить его таймер. Если поток завершится нормально, вызовите обратный вызов, который убьет таймер. Вот простой консольный пример:

using System;
using System.Collections.Generic;
using System.Threading;

namespace ConsoleApplication2
{
    public delegate void KillTimerDelegate(int arg);

    class Program
    {
        static Dictionary<int, Thread> activeThreads = new Dictionary<int, Thread>();
        static Dictionary<int, Timer> activeTimers = new Dictionary<int, Timer>();
        static void Main(string[] args)
        {
            for (int i = 0; i < 10; i++)
            {
                Worker worker = new Worker();
                worker.DoneCallback = new KillTimerDelegate(KillTimer);
                Thread thread = new Thread(worker.DoWork);
                activeThreads.Add(thread.ManagedThreadId, thread);
                thread.IsBackground = true;

                thread.Start();
                Timer timer = new Timer(TimerCallback, thread.ManagedThreadId, 500, 500);
                activeTimers.Add(thread.ManagedThreadId, timer);
            }
            Console.ReadKey();
        }

        static void TimerCallback(object threadIdArg)
        {
            int threadId = (int)threadIdArg;
            if (activeThreads.ContainsKey(threadId))
            {
                Console.WriteLine("Thread id " + threadId.ToString() + " aborted");
                activeThreads[threadId].Abort();
                KillTimer(threadId);
            }
        }

        static void KillTimer(int threadIdArg)
        {
            activeThreads.Remove(threadIdArg);
            activeTimers[threadIdArg].Dispose();
            activeTimers.Remove(threadIdArg);
        }
    }

    public class Worker
    {
        public KillTimerDelegate DoneCallback { get; set; }
        Random rnd = new Random();

        public void DoWork()
        {
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString() + " started");
            Thread.Sleep(rnd.Next(0, 1000));
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString() + " finished normally");
            DoneCallback(Thread.CurrentThread.ManagedThreadId);
        }
    }
}
2
ответ дан 5 December 2019 в 21:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: