Этот ответ предназначен для всех, кто использует WPF для .NET 4.5.
Если вы попытаетесь выполнить Task.Run()
в потоке GUI, тогда task.Wait()
будет вешать бесконечно, если вы не имеют ключевое слово async
в определении вашей функции.
Этот метод расширения решает проблему, проверяя, есть ли мы в потоке графического интерфейса пользователя, и если да, выполняем задачу в потоке диспетчера WPF.
Этот класс может действовать как клей между миром async / await и неасинхронным / ожидающим миром в ситуациях, когда это неизбежно, например свойства MVVM или зависимости от других API, которые не используют async / ожидают.
/// <summary>
/// Intent: runs an async/await task synchronously. Designed for use with WPF.
/// Normally, under WPF, if task.Wait() is executed on the GUI thread without async
/// in the function signature, it will hang with a threading deadlock, this class
/// solves that problem.
/// </summary>
public static class TaskHelper
{
public static void MyRunTaskSynchronously(this Task task)
{
if (MyIfWpfDispatcherThread)
{
var result = Dispatcher.CurrentDispatcher.InvokeAsync(async () => { await task; });
result.Wait();
if (result.Status != DispatcherOperationStatus.Completed)
{
throw new Exception("Error E99213. Task did not run to completion.");
}
}
else
{
task.Wait();
if (task.Status != TaskStatus.RanToCompletion)
{
throw new Exception("Error E33213. Task did not run to completion.");
}
}
}
public static T MyRunTaskSynchronously<T>(this Task<T> task)
{
if (MyIfWpfDispatcherThread)
{
T res = default(T);
var result = Dispatcher.CurrentDispatcher.InvokeAsync(async () => { res = await task; });
result.Wait();
if (result.Status != DispatcherOperationStatus.Completed)
{
throw new Exception("Error E89213. Task did not run to completion.");
}
return res;
}
else
{
T res = default(T);
var result = Task.Run(async () => res = await task);
result.Wait();
if (result.Status != TaskStatus.RanToCompletion)
{
throw new Exception("Error E12823. Task did not run to completion.");
}
return res;
}
}
/// <summary>
/// If the task is running on the WPF dispatcher thread.
/// </summary>
public static bool MyIfWpfDispatcherThread
{
get
{
return Application.Current.Dispatcher.CheckAccess();
}
}
}
Вы должны создать музыку в режиме удержания файла с импульсами + необходимое молчание.
После этого вы можете начать moh, используя действие AGI. Установка музыки, как описано здесь
Progress()
, затем Ringing()
или PlayTones(ring)
. Я видел нескольких провайдеров, где нам нужно было указать звонок с помощью ранних средств массовой информации , например:
exten => 500,1,Progress()
exten => 500,n,Wait(1)
exten => 500,n,Dial(PJSIP/121)
exten => 500,n,Hangup()
и или
exten => 500,1,Progress()
exten => 500,n,PlayTones(ring) <-- OR USE MAYBE Ringing() HERE INSTEAD?
exten => 500,n,Dial(PJSIP/121)
exten => 500,n,Hangup()
и и т. Д.