Обратите внимание на анонимный объект, чтобы получить его имена и значения свойств, затем используйте ExpandoObject, фактически являющийся словарем для его заполнения. Вот пример, выраженный как единичный тест:
[TestMethod]
public void ShouldBeAbleToConvertAnAnonymousObjectToAnExpandoObject()
{
var additionalViewData = new {id = "myControlId", css = "hide well"};
dynamic result = new ExpandoObject();
var dict = (IDictionary<string, object>)result;
foreach (PropertyInfo propertyInfo in additionalViewData.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
dict[propertyInfo.Name] = propertyInfo.GetValue(additionalViewData, null);
}
Assert.AreEqual(result.id, "myControlId");
Assert.AreEqual(result.css, "hide well");
}
Согласно комментарий обновления Prerak K (так как удаленный):
я предполагаю, что не представил вопрос правильно.
ситуация - это: Я хочу загрузить данные в глобальную переменную на основе значения управления. Я не хочу изменять значение управления от дочернего потока. Я не собираюсь делать это когда-либо от дочернего потока.
Поэтому только доступ к значению так, чтобы соответствующие данные могли быть выбраны от базы данных.
решение, которое Вы хотите тогда, должно быть похожим:
UserContrl1_LOadDataMethod()
{
string name = "";
if(textbox1.InvokeRequired)
{
textbox1.Invoke(new MethodInvoker(delegate { name = textbox1.text; }));
}
if(name == "MyName")
{
// do whatever
}
}
Делают Вашу серьезную обработку в отдельном потоке прежде , Вы пытаетесь переключиться назад на поток управления. Например:
UserContrl1_LOadDataMethod()
{
if(textbox1.text=="MyName") //<<======Now it wont give exception**
{
//Load data correspondin to "MyName"
//Populate a globale variable List<string> which will be
//bound to grid at some later stage
if(InvokeRequired)
{
// after we've done all the processing,
this.Invoke(new MethodInvoker(delegate {
// load the control with the appropriate data
}));
return;
}
}
}
Необходимо посмотреть на пример Backgroundworker:
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx Особенно, как это взаимодействует с уровнем UI. На основе Вашей регистрации это, кажется, отвечает на Ваши проблемы.
Средства управления в.NET не вообще ориентированы на многопотоковое исполнение. Это означает, что Вы не должны получать доступ к управлению от потока кроме того, где он живет. Для обхождения этого Вам нужно к , вызывают управление, которое является тем, чего делает попытку Ваш 2-й образец.
Однако в Вашем случае все, что Вы сделали, пасуют назад продолжительный метод к основному потоку. Конечно, это не действительно, что Вы хотите сделать. Необходимо заново продумать это немного так, чтобы все, что Вы делаете на основном потоке, установило быстрое свойство тут и там.
Вы только хотите использовать, Вызывают или BeginInvoke для обрабатываемой детали абсолютного минимума, требуемой изменить UI. Ваш "тяжелый" метод должен выполниться на другом потоке (например, через BackgroundWorker), но тогда использующий Управление. Вызывать/Управлять. BeginInvoke только для обновления UI. Тем путем Ваш поток UI будет свободен обработать события UI и т.д.
, Видят, что мой распараллеливает статью для пример WinForms - хотя статья была написана, прежде чем BackgroundWorker прибыл в сцену, и я боюсь, что не обновил его в этом отношении. BackgroundWorker просто упрощает обратный вызов немного.
Я имел эту проблему с FileSystemWatcher
и нашел, что следующий код решил проблему:
fsw.SynchronizingObject = this
управление тогда использует текущий объект формы для контакта с событиями и поэтому будет на том же потоке.
The cleanest (and proper) solution for UI cross-threading issues is to use SynchronizationContext, see Synchronizing calls to the UI in a multi-threaded application article, it explains it very nicely.