异步短信发送功能未从文本框 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;