Объем переменной - это контекст, в котором он определен. По большей части все переменные PHP имеют только одну область. В эту единую область охвата включены и требуемые файлы. Например:
<?php
$a = 1;
include 'b.inc';
?>
Здесь переменная $a
будет доступна в включенном скрипте b.inc
. Однако в пользовательских функциях вводится локальная функция. Любая переменная, используемая внутри функции, по умолчанию ограничена областью локальных функций. Например:
<?php
$a = 1; /* global scope */
function test()
{
echo $a; /* reference to local scope variable */
}
test();
?>
Этот сценарий не будет выдавать какой-либо вывод, потому что оператор echo ссылается на локальную версию переменной $ a, и ей не присваивается значение в этой области. Вы можете заметить, что это немного отличается от языка C в том, что глобальные переменные в C автоматически доступны для функций, если они не переопределены локальным определением. Это может вызвать некоторые проблемы в том, что люди могут непреднамеренно изменить глобальную переменную. В PHP глобальные переменные должны быть объявлены глобальными внутри функции, если они будут использоваться в этой функции.
Не уверен, что вам действительно нужен MonitoredTask
для этого. Вы можете захватить пользовательскую культуру, используя закрытие:
public static Task ExecuteTask(Action action, string name)
{
var customCulture = CustomCultureInfo.CurrentCulture;
return Task.Factory.StartNew(() =>
{
// use customCulture variable as needed
// inside the generated task.
});
}
Другой способ сделать это - передать текущую культуру как object state
, используя надлежащую перегрузку (либо Action<object>
, либо Func<object, TResult>
):
public static Task ExecuteTask(Action action, string name)
{
var customCulture = CustomCultureInfo.CurrentCulture;
return Task.Factory.StartNew((obj) =>
{
var culture = (CultureInfo) obj;
// use customCulture variable as needed
// inside the generated task.
}, customCulture);
}
Я бы определенно пошел с первым.
Подробнее о закрытии см. в Что такое «замыкания» в .NET?
Чтобы добавить более подробную информацию к @Yuval Itzchakov, я обычно создаю некоторые методы расширения для класса TaskFactory
, которые сохраняют Культуру (обычно я также добавляю тот, который получает действие, которое устанавливает любое заданное свойство в исполняемый поток :
#region StartNewWithPersistedCulture methods
public static Task<TResult> StartNewWithPersistedCulture<TResult>(
this TaskFactory taskFactory, Func<TResult> function, CancellationToken cancellationToken = default (CancellationToken), TaskCreationOptions creationOptions = default (TaskCreationOptions))
{
if (taskFactory == null) throw new ArgumentNullException("taskFactory");
if (function == null) throw new ArgumentNullException("function");
var currentCulture = Thread.CurrentThread.CurrentCulture;
var currentUICulture = Thread.CurrentThread.CurrentUICulture;
return taskFactory.StartNew(
() =>
{
Thread.CurrentThread.CurrentCulture = currentCulture;
Thread.CurrentThread.CurrentUICulture = currentUICulture;
return function();
}, cancellationToken, creationOptions, TaskScheduler.Default);
}
public static Task StartNewWithPersistedCulture(
this TaskFactory taskFactory, Action action, CancellationToken cancellationToken = default (CancellationToken), TaskCreationOptions creationOptions = default (TaskCreationOptions))
{
if (taskFactory == null) throw new ArgumentNullException("taskFactory");
if (action == null) throw new ArgumentNullException("action");
var currentCulture = Thread.CurrentThread.CurrentCulture;
var currentUICulture = Thread.CurrentThread.CurrentUICulture;
return taskFactory.StartNew(
() =>
{
Thread.CurrentThread.CurrentCulture = currentCulture;
Thread.CurrentThread.CurrentUICulture = currentUICulture;
action();
}, cancellationToken, creationOptions, TaskScheduler.Default);
}
#endregion