1

GetUserByID メソッドに問題があったことが判明し、その後ライブラリが更新され、問題が解消されたように見えますが、スレッドから GUI にアクセスする方法を引き続き学習しました。

TweetInvi ライブラリを使用してアプリケーションを作成しました. ユーザーのフォロワーとフォローを取得します. また、彼らの写真, 写真へのリンクと twitter ID.

次に、返されたリストを反復処理して表示します (すべて別のリストに表示されます)。

このアプリケーションを初めて使用したとき、_Click イベントですべてを実行し、完了するまで UI をフリーズしていました。

コードをバックグラウンド ワーカー スレッドに移動したところ、風変わりな問題が発生しています。

特定のリストに入力しないことを「選択」する場合もあれば、入力する場合もあります。時々、あなたをフォローしているリストを除いて、すべてのリストが正しくロードされます。このリストは、どの友達があなたをフォローしているかをフィルタリングします (If ステートメントを使用して、確認済みアカウントを除外します)。

最初に、別のスレッドで UI を更新しようとすると奇妙なエラーが発生する可能性があることを読んだので、入力するリスト以外の UI コントロールの変更をすべて削除しました。

 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {   
            BackgroundWorker worker = sender as BackgroundWorker;


        //user name retrieved from text box, rest of this method will pull various bits of data back

        var username = e.Argument.ToString();
        var user = User.GetUserFromScreenName(username);



        Properties.Settings.Default.LastHandle = boxUsername.Text;
        Properties.Settings.Default.Save();



        var usersTweets = user.GetUserTimeline(Convert.ToInt32(txtTweetAmount.Text)).ToList();

        foreach (var userTweet in usersTweets)
        {
            lstSearchTweetList.Invoke((MethodInvoker)delegate
            {
                var searchList = lstSearchTweetList.Items.Add(userTweet.Text);
                  searchList.SubItems.Add(userTweet.CreatedAt.ToString());
            });
        }


        var show = user.GetFollowers(500).ToList();


        foreach (var friend in show)
        {

            string screenName = "@" + friend.ScreenName;
            lstFriend.BeginInvoke((MethodInvoker)delegate
            {
                lstFriend.Items.Add(screenName); // runs on UI thread
            });

        }

        var friends = user.GetFriends(500);
        var followers = user.GetFollowers(500);


        var result2 = followers.Where(follower => friends.All(friend => follower.Name != friend.Name));
        int i2 = 0;
        foreach (var res2 in result2)
        {
            string screenName = "@" + res2.ScreenName;
            lstFollowingChecker.BeginInvoke((MethodInvoker)delegate
                {
                    lstFollowingChecker.Items.Add(screenName);
                });
                i2++;
             //   lblFollowBackAmount.Text = Convert.ToString(i2);
        }
        var result = friends.Where(friend => followers.All(follower => friend.Name != follower.Name));

        //lblFriendCount.Text = "(" + result.Count().ToString() + ")";
        int i1 = 0;
        foreach (var res in result)
        {
                if (res.Verified != true)
                {
                    string screenName = "@" + res.ScreenName;
                    lstFollowerChecker.BeginInvoke((MethodInvoker)delegate
                    {
                        lstFollowerChecker.Items.Add(screenName);
                    });

                    i1++;
                   // lblCheckerCount.Text = Convert.ToString(i1);
                }
        }



        backgroundWorker1.ReportProgress(1,username);
    }

RunWorkerAsync() を呼び出す関数

private void btnFind_Click(object sender, EventArgs e)
    {

        //start backgroundworker and clear friends and search lists
        pctProgressBar.Visible = true;

        lstFriend.Items.Clear();
        lstSearchTweetList.Items.Clear();
        lstFollowerChecker.Items.Clear();
        lstFollowingChecker.Items.Clear();
        lstFriend.Items.Clear();
        lstSearchTweetList.Items.Clear();

        if (txtTweetAmount.Text == "")
        {
            txtTweetAmount.Text = "20";
        }

        backgroundWorker1.RunWorkerAsync();

    }

私の問題は、不可解な奇妙なエラーがまだ一見ランダムに発生していることです。

これがバックグラウンド ワーカー スレッドでリストが更新されていることが原因である場合、バックグラウンド ワーカーを集中的な作業に使用できない場合、バックグラウンド ワーカーは何に使用されますか?

問題をよりよく示しているので、友人のアカウントの 2 つの写真も含めます。最初の問題は、リストに複数回入力することがあり、「バックリストをフォローしていません」は@Theilluminatiを1回だけ返す必要があることです 同じ画面が初めて

再び @Theilluminati を返しますが、それを 2 回リストします。 同じ画面 2 回目

以下のコードをどこでも実行すると、バックグラウンドワーカーが実行されない、つまり、画像/名前/場所を引き戻すがバックグラウンドワーカーが実行されないという問題もあります。実際に実行しようとするとbackgroundworker スレッドの場合、リストは読み込まれません。

   var username = boxUsername.Text;
    var user = User.GetUserFromScreenName(username);
    //string ImageURL = user.ProfileImageUrl;
    //string biggerImageURL = ImageURL.Replace("_normal", "");
    //txtImageURL.Text = biggerImageURL;
    //pctDisplaypicture.ImageLocation = biggerImageURL;
    //txtTwitterID.Text = user.Id.ToString();
    //lblFriendCount.Text = "(" + user.FollowersCount + ")";

UIスレッドから作業をアンロードできない場合、Backgroundworkerの使用を確認するのに苦労しています。長い投稿で申し訳ありません。読んでくれてありがとう。

修正試行

タスクの実行中に検索ボタンを無効にしましたが、同じ問題が引き続き発生します。

また、タスクが 1 回完了したら、if(working.Cancellationpending == true) を使用してループから抜け出そうとしました。

リストの foreach ループをそれぞれ以下に変更し、ユーザー名をコントロールからプルする代わりに変数として渡しました。問題は悪化したようで、現在はリストがまったく作成されていません。

lstSearchTweetList.Invoke((MethodInvoker)delegate
                {
                    lstSearchTweetList.Items.Add(userTweet.Text).SubItems.Add(userTweet.CreatedAt.ToString());
                });

 backgroundWorker1.RunWorkerAsync(boxUsername.Text);

var username = e.Argument.ToString();

私は解決策として両方の答えを試しましたが、どちらも重大度の異なる同じ問題につながります。名前/画像などを取得するコードのコメントを外すと、バックグラウンドワーカーの実行がブロックされるという問題にまだ悩まされています。どこから実行されても構いません。

4

2 に答える 2

0

コントロールを作成したのと同じスレッドではないスレッドからコントロールにアクセスしないという、Windows GUI プログラミングの基本的な規則に違反しています。このルールを破ると悪いことが起こります ;)

を介してユーザー名の値を渡し、 を介し backgroundWorker1.RunWorkerAsync(boxUsername.Text);て読み取りますe.Arguments as string

次に、 BeginInvokeを使用して UI コントロールを操作する必要があります。理想的には、このラムダを最適化して、コントロールのレイアウトを一時停止し、項目のリスト全体を 1 回の呼び出しで置き換えて、コントロールのレイアウトを再開する必要があります。

 // execute on the UI thread
 this.BeginInvoke((Action)(() =>
 {
   lstFriend.Items.Add("@" + friend.ScreenName);
 }), null);

Control.BeginInvoke同期Control.Invokeオプションよりも非同期を使用します。コントロールが変更をレンダリングするのを待つ理由はないようです。

于 2014-03-16T16:03:42.310 に答える