Ваш код должен быть чем-то вроде этого
$username = $_POST['username'];
$password = $_POST['password'];
$query = "SELECT * FROM Users WHERE UserName LIKE '$username'";
echo $query;
$result = mysql_query($query);
if($result === FALSE) {
die(mysql_error("error message for the user"));
}
while($row = mysql_fetch_array($result))
{
echo $row['FirstName'];
}
. После этого вы получите запрос, напечатанный на экране. Попробуйте выполнить этот запрос на своем сервере и посмотрите, дает ли он желаемые результаты. В большинстве случаев ошибка содержится в запросе. Остальная часть кода верна.
Это обычная проблема с началом работы с людьми. Всякий раз, когда вы обновляете элементы пользовательского интерфейса из потока, отличного от основного потока, вам нужно использовать:
this.Dispatcher.Invoke(() =>
{
...// your code here.
});
Вы также можете использовать control.Dispatcher.CheckAccess()
, чтобы проверить, является ли текущий поток владеет контролем. Если он действительно владеет, ваш код выглядит нормально. В противном случае используйте шаблон выше.
это произошло со мной, потому что я попытался выполнить access UI
компонент в another thread insted of UI thread
, как этот
private void button_Click(object sender, RoutedEventArgs e)
{
new Thread(SyncProcces).Start();
}
private void SyncProcces()
{
string val1 = null, val2 = null;
//here is the problem
val1 = textBox1.Text;//access UI in another thread
val2 = textBox2.Text;//access UI in another thread
localStore = new LocalStore(val1);
remoteStore = new RemoteStore(val2);
}
, чтобы решить эту проблему, обернуть любой вызов ui внутри , о чем упоминал Кандид в своем ответе
private void SyncProcces()
{
string val1 = null, val2 = null;
this.Dispatcher.Invoke((Action)(() =>
{//this refer to form in WPF application
val1 = textBox.Text;
val2 = textBox_Copy.Text;
}));
localStore = new LocalStore(val1);
remoteStore = new RemoteStore(val2 );
}
Кроме того, другое решение гарантирует, что ваши элементы управления создаются в потоке пользовательского интерфейса, а не потоком рабочего потока, например.
Если кто-то пытается работать с BitmapSource
в WPF и потоках и имеет это же сообщение: сначала вызовите метод Freeze()
, прежде чем передать параметр BitmapSource
в качестве параметра потока.
Проблема в том, что вы вызываете GetGridData
из фонового потока. Этот метод обращается к нескольким элементам управления WPF, которые привязаны к основному потоку. Любая попытка доступа к ним из фонового потока приведет к этой ошибке.
Чтобы вернуться к правильной теме, вы должны использовать SynchronizationContext.Current.Post
. Однако в этом конкретном случае, похоже, большая часть работы, которую вы выполняете, основана на пользовательском интерфейсе. Следовательно, вы создадите фоновый поток, чтобы сразу вернуться к потоку пользовательского интерфейса и выполнить некоторую работу. Вам нужно немного реорганизовать свой код, чтобы он мог выполнять дорогостоящую работу в фоновом потоке, а затем публиковать новые данные в потоке пользовательского интерфейса после
Как уже упоминалось здесь , Dispatcher.Invoke
может заморозить UI. Вместо этого используйте Dispatcher.BeginInvoke
.
Вот удобный класс расширений, который упрощает проверку и вызов диспетчера вызовов.
Пример использования: (вызов из окна WPF)
this Dispatcher.InvokeIfRequired(new Action(() =>
{
logTextbox.AppendText(message);
logTextbox.ScrollToEnd();
}));
Класс расширения:
using System;
using System.Windows.Threading;
namespace WpfUtility
{
public static class DispatcherExtension
{
public static void InvokeIfRequired(this Dispatcher dispatcher, Action action)
{
if (dispatcher == null)
{
return;
}
if (!dispatcher.CheckAccess())
{
dispatcher.BeginInvoke(action, DispatcherPriority.ContextIdle);
return;
}
action();
}
}
}
Еще одно полезное использование для Dispatcher.Invoke
- это немедленное обновление пользовательского интерфейса в функции, выполняющей другие задачи:
// Force WPF to render UI changes immediately with this magic line of code...
Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle);
Я использую это, чтобы обновить текст кнопки до « Обработка ... "и отключить его при выполнении запросов WebClient
.
Я также обнаружил, что System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke()
не всегда является диспетчером целевого контроля, точно так же, как dotNet пишет в своем ответе. У меня не было доступа к диспетчеру управления, поэтому я использовал Application.Current.Dispatcher
, и он решил проблему.
По какой-то причине ответ Кандиде не строился. Это было полезно, однако, поскольку это заставило меня найти это, которое отлично работало:
System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke((Action)(() =>
{
//your code here...
}));
Это работает для меня.
new Thread(() =>
{
Thread.CurrentThread.IsBackground = false;
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, (SendOrPostCallback)delegate {
//Your Code here.
}, null);
}).Start();
Вам нужно обновить пользовательский интерфейс, поэтому используйте
Dispatcher.BeginInvoke(new Action(() => {GetGridData(null, 0)}));
Я продолжал получать ошибку, когда добавлял каскадные comboboxes в свое приложение WPF и разрешал ошибку с помощью этого API:
using System.Windows.Data;
private readonly object _lock = new object();
private CustomObservableCollection<string> _myUiBoundProperty;
public CustomObservableCollection<string> MyUiBoundProperty
{
get { return _myUiBoundProperty; }
set
{
if (value == _myUiBoundProperty) return;
_myUiBoundProperty = value;
NotifyPropertyChanged(nameof(MyUiBoundProperty));
}
}
public MyViewModelCtor(INavigationService navigationService)
{
// Other code...
BindingOperations.EnableCollectionSynchronization(AvailableDefectSubCategories, _lock );
}