Это общая проблема, с которой люди сталкиваются в WPF. Я полагаю, что вы пытаетесь обновить метку из BackgroundWorker, и вас мучают ошибки "другой поток владеет этим". Вы, вероятно, найдете ответы, в которых вам предлагается использовать диспетчер для обновления вашего ярлыка. НЕ ДЕЛАЙТЕ ЭТОГО! Это ненадежно и часто не обновляется при больших нагрузках. Вы должны использовать правильные методы привязки в вашем случае.
Надеемся, что этот пример (хотя и не обязательно самый рефакторированный, но и не самый быстрый для реализации) может помочь вам начать правильный путь, объяснив некоторые основные принципы или WPF.
Создайте наблюдаемый класс, который реализует INotifyPropertyChanged
. Это твоя модель. Это в основном оболочка того, как будут храниться ваши данные (в вашем случае это статус).
using System.ComponentModel;
public class Status_Update : INotifyPropertyChanged
{
//private property that stores value
private string status;
//public property the gets & sets value
public string Status
{
get {return status;}
set
{
if(status != value)
{
status = value;
NotifyPropertyChanged("Status");
}
}
}
//Logic to notify that property values have changed.
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
Теперь давайте перейдем к коду вашего элемента управления или окна за конструктором.
//Create a Status_Update object in your control.
public Status_Update My_Status {get;set;}
public My_Control_or_Window()
{
//Initialize the Status_Update object
MyStatus = new Status_Update(){Status=""};
InitializeComponent();
//Set the controls DataContext to itself in the constructor
DataContext=this;
}
Теперь в XAML вашего веб-интерфейса вы просто привязываетесь к свойству элемента управления MyStatus.Status
, и он готов к оперативным обновлениям из любого вызывающего потока.
<Label Content={Binding MyStatus.Status, UpdateSourceTrigger=PropertyChanged}/>
Для обновления просто установите значение MyStatus.Status
в BackgroundWorker.
private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
MyStatus.Status = "Updating the first item";
Some_Task();
MyStatus.Status = "Updating the next item";
Some_Task();
}
Хочу заметить, что этот пример не лучший пример MVVM и не лучшая структура кода для того, что вы пытаетесь сделать, но он должен помочь вам лучше понять, как работает связывание в WPF и о том, как с ним гораздо проще обновлять такие вещи, как метка состояния. Требуется немного больше работы на переднем конце, но экономит так много времени на заднем конце.
Желаем удачи.
(РЕДАКТИРОВАНИЕ: Удаленное ненужное использование StackTrace
самостоятельно - который был бы полезен, если бы Вы хотели распечатать больше информации, чем всего один кадр.)
Можно использовать StackFrame
класс, но это довольно дорого (IIRC) и может быть немного неправильно из-за встраивания.
Править: Что-то вроде этого: (NoInlining должен удостовериться, что ведет себя правильно...),
Imports System.Diagnostics
Imports System.Runtime.CompilerServices
Public Class Test
Shared Sub Main()
Something()
End Sub
<MethodImpl(MethodImplOptions.NoInlining)> _
Shared Sub Something()
Functions.LogInfo("some text")
End Sub
End Class
Public Class Functions
<MethodImpl(MethodImplOptions.NoInlining)> _
Public Shared Sub LogInfo (ByVal entry as String)
Dim frame as StackFrame = new StackFrame(1, False)
Console.WriteLine("{0}: {1}", _
frame.GetMethod.Name, _
entry)
End Sub
End Class
Смотрите на то, Как я могу найти метод который названным существующим методом?.
Переведенный в VB (надо надеяться):
Imports System.Diagnostics
''// get call stack
Dim stackTrace As New StackTrace()
''// get calling method name
Console.WriteLine(stackTrace.GetFrame(1).GetMethod().Name)
Можно использовать StackFrame или StackTrace. Но Ваше поведение могло бы отличающийся в сборках конечных версий по сравнению с выполнением в отладчике из-за встраивания. Таким образом, Ваши результаты могли бы быть не то, что Вы ожидаете:
c#:
System.Diagnostics.StackFrame sf = new StackFrame(1);
sf.GetMethod().Name;
vb:
Dim sf as new StackFrame(1)
sf.GetMethod().Name
Извините просто реализованный Вы попросили vb.net. Я отредактировал свой ответ, но vb синтаксис не мог бы быть правильным
System.Reflection.MethodBase.GetCurrentMethod.Name делает то же самое, и кажется, что получить зависание