Ответ 1
Можете ли вы использовать задачу?
Task.Factory.StartNew(() =>
{
System.Threading.Thread.Sleep(Interval);
TheMethod();
});
Понятно: например, представьте себе кнопку в моей форме. Когда пользователь нажимает на кнопку, некоторый метод void должен запускаться через 30 секунд.
Был бы пустой метод DoAfterDelay
который принимает два входных параметра. Первый метод - это метод (с использованием делегатов), а второй - временной интервал. Итак, я буду иметь:
public delegate void IVoidDelegate();
static void DoAfterDelay(IVoidDelegate TheMethod, TimeSpan Interval)
{
// *** Some code that will pause the process for "Interval".
TheMethod();
}
Итак, мне просто нужен кусок кода, чтобы приостановить процесс на определенный промежуток времени. До этого я использовал этот код для этого:
System.Threading.Thread.Sleep(Interval);
Но этот код мне не подходит, потому что он останавливает весь процесс и останавливает программу. Я не хочу, чтобы программа застряла в методе DoAfterDelay
. Вот почему Thread.Sleep
бесполезен.
Так кто-нибудь может предложить лучший способ? Конечно, я искал об этом, но большинство решений, которые я нашел, были основаны на использовании таймера (как здесь, например). Но использование таймера - мое последнее мнение, потому что метод должен запускаться один раз, а использование таймеров делает программу непонятной для чтения. Поэтому я ищу лучшее решение, если оно есть. Или, может быть, я должен использовать таймеры?
Я думаю, что я должен играть с темами, но не уверен. Поэтому мне интересно, если кто-нибудь может привести меня к решению. Заранее спасибо.
Можете ли вы использовать задачу?
Task.Factory.StartNew(() =>
{
System.Threading.Thread.Sleep(Interval);
TheMethod();
});
Здесь вы можете использовать функцию async для ожидания .Net 4.5
Вы можете использовать Task.Delay и дать задержку в милисекундах. Это очень чистый способ. например:
private async void button1_Click(object sender, EventArgs e)
{
await Task.Delay(5000);
TheMethod();
}
DoAfterDelay запускает таймер, который запускается только один раз, когда он истекает, он вызывает вашу функцию "TheMethod". Почему это было бы грязно?
Вот что вы хотите:
public static void Example1c()
{
Action action = DoSomethingCool;
TimeSpan span = new TimeSpan(0, 0, 0, 5);
ThreadStart start = delegate { RunAfterTimespan(action, span); };
Thread t4 = new Thread(start);
t4.Start();
MessageBox.Show("Thread has been launched");
}
public static void RunAfterTimespan(Action action, TimeSpan span)
{
Thread.Sleep(span);
action();
}
private static void DoSomethingCool()
{
MessageBox.Show("I'm doing something cool");
}
Одним из преимуществ использования Action является то, что его можно легко изменить, чтобы передать параметры. Предположим, вы хотите передать целое число в DoSomethingCool. Просто измените так:
public static void Example1c()
{
Action<int> action = DoSomethingCool;
TimeSpan span = new TimeSpan(0, 0, 0, 5);
int number = 10;
ThreadStart start = delegate { RunAfterTimespan(action, span, number); };
Thread t4 = new Thread(start);
t4.Start();
MessageBox.Show("Thread has been launched");
}
public static void RunAfterTimespan(Action<int> action, TimeSpan span, int number)
{
Thread.Sleep(span);
action(number);
}
private static void DoSomethingCool(int number)
{
MessageBox.Show("I'm doing something cool");
}
Очень гибкий...
Существует несколько способов создания потоков, но, конечно, это зависит от того, что вы делаете. Вы можете создать поток на лету, как это:
Thread aNewThread = new Thread(
() => OnGoingFunction()
);
aNewThread.Start();
Этот поток будет работать в фоновом режиме. Функция, которую вы хотите сделать, должна иметь метод сна для сна, когда выполняется ее обработка. Так что-то вроде этого:
private void OnGoingFunction()
{
//Code....
Thread.Sleep(100); //100 ms, this is in the thead so it will not stop your winForm
//More code....
}
Я надеюсь, что это поможет.
Другой вариант - создать поток всякий раз, когда вам нужно его обработать, и не беспокоиться о опции сна. Просто создайте новый поток каждый раз, чтобы загрузить процесс
Вы должны создать Coroutine
public IEnumerator waitAndRun()
{
// WAIT FOR 3 SEC
yield return new WaitForSeconds(3);
// RUN YOUR CODE HERE ...
}
И назовите его с помощью:
StartCoroutine(waitAndRun());
Вы можете указать точные секунды, используя
DateTime runTime = new DateTime();
double waitSeconds = (runTime - DateTime.Now).TotalSeconds;
Task.Factory.StartNew(() =>
{
Thread.Sleep(TimeSpan.FromSeconds(waitSeconds));
YourMethod();
});
runTime => Когда вы хотите выполнить метод.