Dispatcher.Invoke - это хороший способ обновления вашего пользовательского интерфейса. Действия пользовательского интерфейса должны выполняться потоком пользовательского интерфейса, об этом позаботится диспетчер.
Вы можете сделать свой код немного короче, используя лямбда-выражения:
Dispatcher.Invoke((Action<string>) ((data) => { label1.Content = data; }));
Я бы также предложил поставить прокси в операторе Using, чтобы это было:
int result = 0;
using (CalculatorServiceClient proxy = new CalculatorServiceClient()) {
AsyncCallback callback = new AsyncCallback((asyncResult) => {
result = proxy.EndAdd(asyncResult);
Dispatcher.Invoke((Action<string>) ((data) => { label1.Content = data; }));
});
proxy.BeginAdd(Convert.ToInt32(txtNumber1.Text), Convert.ToInt32(txtNumber2.Text), callback, null);
}
Или, если вам нравится коротко:
int result = 0;
using (CalculatorServiceClient proxy = new CalculatorServiceClient())
proxy.BeginAdd(Convert.ToInt32(txtNumber1.Text), Convert.ToInt32(txtNumber2.Text), new AsyncCallback((asyncResult) => {
result = proxy.EndAdd(asyncResult);
Dispatcher.Invoke((Action<string>) ((data) => { label1.Content = data; }));
}), null);