Может ли кто-нибудь помочь мне, у меня проблема. Я пытаюсь заставить этот код работать в фоновом режиме через пул потоков, но я не могу заставить его работать, я продолжаю получать эту ошибку:
Cross-thread operation not valid: Control 'ListBox3' accessed
from a thread other than the thread it was created on.
Вот код, который я использую:
private void DoWork(object o)
{
var list = ListBox3;
var request = createRequest(TxtServer.Text, WebRequestMethods.Ftp.ListDirectory);
using (var response = (FtpWebResponse)request.GetResponse())
{
using (var stream = response.GetResponseStream())
{
using (var reader = new StreamReader(stream, true))
{
while (!reader.EndOfStream)
{
list.Items.Add(reader.ReadLine());
ResultLabel.Text = "Connected";
}
}
}
}
}
Ответ 2 · рейтинг 9 · Parviz Bazgosha
Вы можете получить доступ к управлению, сделав это
Invoke(new Action(() => {Foo.Text="Hi";}));
Ответ 3 · рейтинг 3 · SkeetJon
Этот метод расширения также решает проблему.
/// <summary>
/// Allows thread safe updates of UI components
/// </summary>
public static void InvokeEx<T>(this T @this, Action<T> action) where T : ISynchronizeInvoke
{
if (@this.InvokeRequired)
{
@this.Invoke(action, new object[] { @this });
}
else
{
action(@this);
}
}
Используйте в своем рабочем потоке следующим образом
InvokeEx(x => x.MyControl.Text = "foo");
Ответ 4 · рейтинг 3 · Steve
Вы также можете получить доступ к элементам управления с помощью вызова, используя следующий синтаксис с делегатом действия:
Invoke((Action)(() =>
{
var myVar = SomeWinFormControl.Property;
}));
Ответ 5 · рейтинг 2 · Dan OConnell
Вы не можете получить доступ к элементу управления из отдельного потока, он должен быть из того же потока, из которого был создан элемент управления.
Ответ 6 · рейтинг 1 · Brian Rasmussen
Я предполагаю, что DoWork запускается в другом потоке. Код обращается к элементу ListBox3, который является элементом управления с графическим интерфейсом. .NET ограничивает доступ к элементам управления GUI тем потоком, который их создал.
Ответ 7 · рейтинг 1 · Community
Вы можете сделать это вместо этого, так как доступ к элементам управления из другого потока, кроме потока пользовательского интерфейса, требует вызова.
Когда вы начинаете (я предполагаю, что вы используете BackgroundWorker), передайте URL-адрес из текстового поля в RunWorkerAsync(TxtServer.Text) в качестве аргумента, затем:
private void DoWork(object o, DoWorkEventArgs e)
{
string Url = (string) e.Argument;
List<of string> tmpList = new List<of string>;
var request = createRequest(url, WebRequestMethods.Ftp.ListDirectory);
using (var response = (FtpWebResponse)request.GetResponse())
{
using (var stream = response.GetResponseStream())
{
using (var reader = new StreamReader(stream, true))
{
while (!reader.EndOfStream)
{
list.Add(reader.ReadLine());
//ResultLabel.Text = "Connected";
//use reportprogress() instead
}
}
}
}
e.result = tmpList;
}
Затем в своем событии Completed приведите e.result к списку и добавьте его в свой контроль.