質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Q&A

解決済

3回答

2482閲覧

c#で非同期処理について教えてください

naka1220

総合スコア15

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

0グッド

1クリップ

投稿2018/03/24 04:34

前提・実現したいこと

テキストデータを読み込んでコンソール画面に表示するだけのコードですが、
非同期処理を勉強中で、以下に書いてみました。
コンソール画面に何も表示されなく、データを読み込めていないのか、
それとも非同期処理の記述がまちがっているのか、わかりません。
そもそも非同期処理の書き方が出来ているか疑問ですが…
c#勉強中の初心者ですが、教えて頂けたらと思います。
よろしくお願いいたします。

発生している問題・エラーメッセージ

コンソール画面に読み込んだデータが表示されない

該当のソースコード

c#

1using System.Threading.Tasks; 2using System.IO; 3using System.Text; 4using System; 5using System.Linq; 6using System.Collections.Generic; 7 8public class CSV 9{ 10 public static Task<string[]> Data() 11 { 12 var Task = new Task<string[]>(() => 13 { 14 List<string> list = new List<string>(); 15 16 StreamReader Sr = new StreamReader(Path, Encoding.UTF8); 17 18 while(Sr.ReadLine() != null) 19 { 20 string[] line = Sr.ReadLine().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToArray(); 21 foreach (string s in line.Take(0)) 22 { 23 list.Add(s); 24 } 25 } 26 return list.ToArray(); 27 }); 28 Task.Start(); 29 return Task; 30 } 31 public static async void Print() 32 { 33 string[] x = await Data(); 34 Console.Write("{0}",x[0]); 35 } 36 public static void Main() 37 { 38 Print(); 39 } 40}

試したこと

補足情報(FW/ツールのバージョンなど)

Visual Studio Community 2017
.Net FrameWork 4.6.1

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2018/03/24 06:33

これ、コンパイル通りませんねー。ツッコミどころはいくつもあるけど
guest

回答3

0

Pathが未定義
Dateのナカミのスレッドが動くのはPrint関数が終わってから(というか、Print関数の実行でスレッドが起動される)

そもそも動かないけど、

while(Sr.ReadLine() != null)

1行読み飛ばしてるけど、そんでいいの?

string[] line = Sr.ReadLine().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToArray();

最後のToArray いらない。SplitはString[]をかえします

foreach (string s in line.Take(0))

Take(0) ってなにこれー
ここのループ、line をlist に追加したいなら
list.AddRange(line);
でいいぢゃん(ちがうの?)

投稿2018/03/24 06:59

y_waiwai

総合スコア87719

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

naka1220

2018/03/24 07:26

Pathは定義というか、読み込みたいファイルのフルパス入れていました。 Take(0)は、読み込み行の1列目をとってlistに追加したいということで書いていました。 以下のように書き直してみましたが、コンパイルエラーとはならず、何も表示されません。 どうしたらよいかご教授お願いいたします。 public class CSV { public static Task<string[]> DataAsync() { var Task = new Task<string[]>(() => { List<string> list = new List<string>(); StreamReader Sr = new StreamReader(@"Path", Encoding.UTF8); while (!Sr.EndOfStream) { string[] line = Sr.ReadLine().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); list.AddRange(line); } Sr.Close(); return list.ToArray(); }); Task.Start(); return Task; } public static async void Print() { string[] x = await DataAsync(); Console.Write("{0}", x[0]); } public static void Main() { Print(); } }
y_waiwai

2018/03/24 07:32

最初の列を入れるだけなら、 list.Add(line[0]); だけでいけます。 タスクの実行待ちは、他の回答で触れられているのでそっちを参照してください ちなみに、print関数のasync とawaitは外しときましょう
naka1220

2018/03/24 07:36

list.Add(line[0]);でいけるのですね、わかりました。 まだ勉強し始めて間もないので、ご迷惑おかけしました。 ありがとうございます。
y_waiwai

2018/03/24 07:38

んでたぶんVisualStudioで書いてると思いますが、止めたい行にブレークポイントを設定してやればプログラムを実行したときにそこで止まってくれます(そして変数などの値が参照できる) 「VisualStudio ブレークポイント」でぐぐると解説が引っかかります main関数内のprint(); のあとに、while(true); を追加しておいて、Taskのナカミがいつ実行されるかを見てみよう
naka1220

2018/03/24 07:42

Taskの中身がいつ実行されるかをブレークポイント設定で見ること、わかりました。ありがとうございます
y_waiwai

2018/03/24 09:31

C#で非同期処理を実行する、という場合、色んな方法があります 1.Taskクラスを生成する 2.デリゲートからBeginInvoke 3.async/awaitスキームを使う この他にもいろいろ方法があると思います。 イマドキの方法としては、1を使うよりも、3を使用するように言われています ということで、これから学ぶ、という場合には3を覚えるようにすればいいかと思います #私は手軽なので2を多用してますがw
guest

0

Print();Print().GetAwaiter().GetResult(); としたらどうなりますか?

期待通り非同期で動いているとすると、Print(); としてはダメなはずです。

そのようにすると、ファイルから読んできたりプリントしたりするコードは別のスレッドで動いて、Main プログラムは直ちに終了してしまうはずです。

それが期待通りいかない原因だと思います。

あと、Data メソッドの書き方を、async, await キーワードと非同期版のメソッド ReadLineAsync を使って書き直した方がよさそうです。

投稿2018/03/24 06:43

編集2018/03/24 06:46
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

naka1220

2018/03/24 07:29

Print().GetAwaiter().GetResult();とするとビルドできませんでした。
退会済みユーザー

退会済みユーザー

2018/03/24 07:46

Data メソッドが間違っているのでは? 上にも書きましたが、async, await キーワードと非同期版のメソッド ReadLineAsync を使って書き直してはいかがですか。
naka1220

2018/03/24 07:49

ReadLineAsyncではSplit関数が使えないと出ました。 なにか方法はあるのでしょうか
退会済みユーザー

退会済みユーザー

2018/03/24 07:56

await しないとダメです。やってないでしょ?
naka1220

2018/03/24 08:20

してませんでした、やってみます。 別の方から、コード頂きましたが、 最初の自分のコードも大幅に修正してみます。 ありがとうございます。また質問してもよいでしょうか
退会済みユーザー

退会済みユーザー

2018/03/24 09:44

> また質問してもよいでしょうか もちろん質問はご自由にどうぞ。だた、質問を見つけられなかったり、回答を持っていなくて、回答できなかった場合はすみません。
guest

0

ベストアンサー

コンパイルできません。
コンパイルできてもまともに動きません。
問題が多すぎて面倒なので大幅に書き直しました。

C#

1using System; 2using System.Collections.Generic; 3using System.IO; 4using System.Linq; 5using System.Threading.Tasks; 6 7namespace ConsoleApp1 8{ 9 class Program 10 { 11 public static async Task<IEnumerable<IList<string>>> Data() 12 { 13 return await Task.Run(() => 14 { 15 var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TextFile1.txt"); 16 return File 17 .ReadLines(path) 18 .Select(a => a.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList()); 19 }); 20 } 21 public static async Task Print() 22 { 23 var x = await Data(); 24 Console.Write("{0}", x.ToList()[0][0]); 25 } 26 public static void Main() 27 { 28 Print().Wait(); 29 Console.ReadKey(); 30 } 31 } 32}

TextFile1.txt

1 2 3 4 5 6 7 8 9

出力

1

投稿2018/03/24 07:25

Zuishin

総合スコア28656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

naka1220

2018/03/24 07:47

ありがとうございます 読み込んでくれました。 もうちょっと勉強しないといけませんね、申し訳ありません。
naka1220

2018/03/24 08:04

難しそうですが、勉強してみます。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問