异步短信发送功能未从文本框 WPF c# 获取数据
async SMS sending function is not getting data from textbox WPF c#
我正在尝试制作一个异步函数,通过循环从网格视图中获取数据来一条一条地发送文本消息。
到目前为止我所做的如下:
public async void asyncSmsSend()
{
try
{
btnSend.Content = "Sending...";
await sendSmsFunc();
btnSend.Content = "Sent";
}
catch (Exception)
{
throw;
}
}
private Task sendSmsFunc()
{
return Task.Factory.StartNew(() =>
{
try
{
srprt = new SerialPort(prt, 115200);
Thread.Sleep(1000);
srprt.Open();
Thread.Sleep(1000);
srprt.Write("AT+CMGF=1\r");
Thread.Sleep(1000);
srprt.Write("AT+CMGS=\"" +tbNmber.Text+ "\"\r\r");
Thread.Sleep(1000);
srprt.Write(tbMessage.Text + "\x1A");
Thread.Sleep(1000);
//btnSend.Content = "Sent";
srprt.Close();
}
catch (Exception ex)
{
//btnSend.Content = "Failed";
MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
//btnSend.Content = "Send Again";
}
});
}
目前我只是想通过从表单上的文本框中获取数据来发送异步消息,它给了我
"The calling thread cannot access this object because a different thread owns it"
因为我是这类编程的新手,需要帮助。
PS。在出现上述问题之后,我将不得不使用以下方法从 DataGridView 中一个一个地获取值并异步发送消息。请告诉我如何使用循环。
谢谢
int i = dgvResults.SelectedIndex;
DataRowView v = (DataRowView)dgvResults.Items[i];
sIDCardNum = (string)v[0];
Name = (string)v[1];
Nmbr = (string)v[3];
Msg = (string)v[4];
你不能从另一个线程访问 UI 控件,唯一允许的线程是 UI 线程,要解决这个问题,你有两个解决方案,要么分别使用 Dispatcher BeginInvoke当你像这样使用 UI 元素时:
...
srprt.Write("AT+CMGF=1\r");
Thread.Sleep(1000);
Application.Current.Dispatcher.BeginInvoke(new Action(async () =>
{
srprt.Write("AT+CMGS=\"" + tbNmber.Text + "\"\r\r");
}));
Thread.Sleep(1000);
Application.Current.Dispatcher.BeginInvoke(new Action(async () =>
{
srprt.Write(tbMessage.Text + "\x1A");
}));
...
或者不从该异步方法访问这些控件并将所需的参数传递给它
private Task sendSmsFunc(string phoneNumber,string message)
更新
关于您关于如何循环访问 GridView 项目列表的第二个问题,最佳和优雅的解决方案如下:
-定义一个适当的模型来保存每一行的信息假设一个 class 人:
public class Person
{
public String Name { get; set; }
public String PhoneNumber { get; set; }
public String Message { get; set; }
}
-在你的window代码隐藏(或ViewModel)中,首先实现INotifyPropertyChanged
接口(这是一种通知UI每次更新属性 已更改 ) 并创建该模型的集合:
public partial class MainWindow : Window,INotifyPropertyChanged
{
private ObservableCollection<Person> _peopleCollection;
public ObservableCollection<Person> PeopleCollection
{
get { return _peopleCollection; }
set
{
if (Equals(value, _peopleCollection)) return;
_peopleCollection = value;
OnPropertyChanged();
}
}
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
PeopleCollection = new ObservableCollection<Person>()
{
new Person(){Name = "Person1" ,PhoneNumber = "num1"},
new Person(){Name = "Person2" ,PhoneNumber = "num2"}
};
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
-在Xaml中定义你的UI:
<ListView ItemsSource="{Binding PeopleCollection}">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Number" DisplayMemberBinding="{Binding PhoneNumber}"/>
<GridViewColumn Header="Message" DisplayMemberBinding="{Binding Message}"/>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
<Button VerticalAlignment="Bottom" Content="Loop" Click="ButtonBase_OnClick"></Button>
-要循环遍历 GridView 项目,您需要做的就是循环遍历 ObservableCollection
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
foreach (var person in PeopleCollection)
{
await sendSmsFunc(person.PhoneNumber, person.Message);
}
}
Ps:不要忘记设置 DataContext
:
this.DataContext = this;
我正在尝试制作一个异步函数,通过循环从网格视图中获取数据来一条一条地发送文本消息。
到目前为止我所做的如下:
public async void asyncSmsSend()
{
try
{
btnSend.Content = "Sending...";
await sendSmsFunc();
btnSend.Content = "Sent";
}
catch (Exception)
{
throw;
}
}
private Task sendSmsFunc()
{
return Task.Factory.StartNew(() =>
{
try
{
srprt = new SerialPort(prt, 115200);
Thread.Sleep(1000);
srprt.Open();
Thread.Sleep(1000);
srprt.Write("AT+CMGF=1\r");
Thread.Sleep(1000);
srprt.Write("AT+CMGS=\"" +tbNmber.Text+ "\"\r\r");
Thread.Sleep(1000);
srprt.Write(tbMessage.Text + "\x1A");
Thread.Sleep(1000);
//btnSend.Content = "Sent";
srprt.Close();
}
catch (Exception ex)
{
//btnSend.Content = "Failed";
MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
//btnSend.Content = "Send Again";
}
});
}
目前我只是想通过从表单上的文本框中获取数据来发送异步消息,它给了我
"The calling thread cannot access this object because a different thread owns it" 因为我是这类编程的新手,需要帮助。
PS。在出现上述问题之后,我将不得不使用以下方法从 DataGridView 中一个一个地获取值并异步发送消息。请告诉我如何使用循环。 谢谢
int i = dgvResults.SelectedIndex;
DataRowView v = (DataRowView)dgvResults.Items[i];
sIDCardNum = (string)v[0];
Name = (string)v[1];
Nmbr = (string)v[3];
Msg = (string)v[4];
你不能从另一个线程访问 UI 控件,唯一允许的线程是 UI 线程,要解决这个问题,你有两个解决方案,要么分别使用 Dispatcher BeginInvoke当你像这样使用 UI 元素时:
...
srprt.Write("AT+CMGF=1\r");
Thread.Sleep(1000);
Application.Current.Dispatcher.BeginInvoke(new Action(async () =>
{
srprt.Write("AT+CMGS=\"" + tbNmber.Text + "\"\r\r");
}));
Thread.Sleep(1000);
Application.Current.Dispatcher.BeginInvoke(new Action(async () =>
{
srprt.Write(tbMessage.Text + "\x1A");
}));
...
或者不从该异步方法访问这些控件并将所需的参数传递给它
private Task sendSmsFunc(string phoneNumber,string message)
更新
关于您关于如何循环访问 GridView 项目列表的第二个问题,最佳和优雅的解决方案如下:
-定义一个适当的模型来保存每一行的信息假设一个 class 人:
public class Person
{
public String Name { get; set; }
public String PhoneNumber { get; set; }
public String Message { get; set; }
}
-在你的window代码隐藏(或ViewModel)中,首先实现INotifyPropertyChanged
接口(这是一种通知UI每次更新属性 已更改 ) 并创建该模型的集合:
public partial class MainWindow : Window,INotifyPropertyChanged
{
private ObservableCollection<Person> _peopleCollection;
public ObservableCollection<Person> PeopleCollection
{
get { return _peopleCollection; }
set
{
if (Equals(value, _peopleCollection)) return;
_peopleCollection = value;
OnPropertyChanged();
}
}
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
PeopleCollection = new ObservableCollection<Person>()
{
new Person(){Name = "Person1" ,PhoneNumber = "num1"},
new Person(){Name = "Person2" ,PhoneNumber = "num2"}
};
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
-在Xaml中定义你的UI:
<ListView ItemsSource="{Binding PeopleCollection}">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Number" DisplayMemberBinding="{Binding PhoneNumber}"/>
<GridViewColumn Header="Message" DisplayMemberBinding="{Binding Message}"/>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
<Button VerticalAlignment="Bottom" Content="Loop" Click="ButtonBase_OnClick"></Button>
-要循环遍历 GridView 项目,您需要做的就是循环遍历 ObservableCollection
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
foreach (var person in PeopleCollection)
{
await sendSmsFunc(person.PhoneNumber, person.Message);
}
}
Ps:不要忘记设置 DataContext
:
this.DataContext = this;