#c#
#c#
Вопрос:
Я пытался изучить делегатов.Я только что создал кнопку, метку и флажок. Если я нажму флажок, формат времени изменится. Если я нажму на кнопку, я напечатаю соответствующую дату. Однако при попытке использовать асинхронный делегат, т. Е. Использовать другой поток, я застрял с ошибкой
public delegate void AsyncDelegate(bool seconds);
public partial class Form1 : Form
{
AsyncDelegate ad;
TimeZ t = new TimeZ();
public Form1()
{
InitializeComponent();
}
private void btn_async_Click(object sender, EventArgs e)
{
ad = new AsyncDelegate(t.GetTime);
AsyncCallback acb = new AsyncCallback(CB);
if (chk_sec.Checked)
{
ad.BeginInvoke(true, acb, null);
}
else
ad.BeginInvoke(false, acb, null);
}
public void CB(IAsyncResult ar)
{
t.Tim = ar.ToString();
ad.EndInvoke(ar);
lbl_time.Text = t.Tim;
}
и в другой библиотеке классов я получаю Timez, использованный выше. Я добавляю ссылку на нее в проект
public class TimeZ
{
private string tim;
public string Tim
{
get
{
return tim;
}
set
{
tim = value;
}
}
public string GetTime(bool seconds)
{
if (seconds)
{
return DateTime.Now.ToLongTimeString();
}
else
return DateTime.Now.ToShortTimeString();
}
}
Однако я получаю эту ошибку при запуске программы:
Cross-thread operation not valid: Control 'lbl_time' accessed from a thread other than
the thread it was created on.
Можете ли вы помочь мне решить эту проблему?
Комментарии:
1. У меня в голове не укладывается, что кто-то может проголосовать за это. Что вы вообще пытаетесь сделать с этим кодом?
Ответ №1:
Вы не можете получить доступ к свойствам и методам форм и элементов управления из потока, который не является потоком формы.
В Windows каждое окно привязано к потоку, который его создал.
Вы можете сделать это только с помощью Control .BeginInvoke или более полезная система.Многопоточность.Класс SynchronizationContext.
См. http://msdn.microsoft.com/it-it/library/0b1bf3y3 (v= против 80).aspx
Это означает, что вам нужно опубликовать через контекст синхронизации, например, другой асинхронный делегат в потоке формы.
public partial class Form1 : Form
{
AsyncDelegate ad;
TimeZ t = new TimeZ();
// Our synchronization context
SynchronizationContext syncContext;
public Form1()
{
InitializeComponent();
// Initialize the synchronization context field
syncContext = SynchronizationContext.Current;
}
private void btn_async_Click(object sender, EventArgs e)
{
ad = new AsyncDelegate(t.GetTime);
AsyncCallback acb = new AsyncCallback(CB);
if (chk_sec.Checked)
{
ad.BeginInvoke(true, acb, null);
}
else
{
ad.BeginInvoke(false, acb, null);
}
}
public void CB(IAsyncResult ar)
{
// this will be executed in another thread
t.Tim = ar.ToString(); // ar.ToString()???? this will not give you the time for sure! why?
ad.EndInvoke(ar);
syncContext.Post(delegate(object state)
{
// This will be executed again in form thread
lbl_time.Text = t.Tim;
}, null);
}
Однако я не знаю, зачем вам нужен асинхронный обратный вызов для времени печати 🙂 на самом деле не знаю почему, думая, что это просто какой-то тестовый код.
Комментарии:
1. я не знаю, где я ошибаюсь, но теперь он выводит System.Remote. Удаленное подключение. Обмен сообщениями. Результат AsyncResult, а не текущая дата
2. Это означает, что он работает сейчас, но в вашем коде все еще есть что-то еще «неправильное». lbl_time. Текст = XXXXXX;