ちくのう症(蓄膿症)は「菌」が原因!?

こんちは。最近C#をやり始めて行き詰まったので質問致します。
質問内容に対する答えをお持ちの方がいらっしゃいましたら、お暇な時にでもお答えください。

public Class SumLoop {
public Keisan(int Cnt, string Msg) {
  // (1)プログレスバーのフォーム生成時に変数Cntをプログレスバーの最大値、変数Msgをフォームのタイトルに設定したい。
  FormProgress FrmPro = new FormProgress();
 Thread thread = new Thread(new ThreadStart((2)) );
  thread.Start();
  for(int i=0; i<Cnt; i++) { 
 // (3)このiがインクリメントする度にプログレスバーのValueを増やしたい
  // FrmPro.SetProgressValue(i) // これだとコンパイラに怒られた

   // ここに主な処理
  }
}

public partial class FormProgress : System.Windows.Forms.Form {
 public FormDfmProgress() { InitializeComponent(); }

 // (3)これではダメみたい
 public void SetprogressValue(int iValue) {
  progressBar1.Value = iValue;
  progressBar1.Refresh();
 }
 // (4)他のイベントが必要?
}


ざっと汚いコードを書きましたが具体的にお知恵を貸して頂きたいところは

(1)のフォーム生成時のパラメータをどう与えるのか?
インスタンス作成の際にここで言うFormDfmProgressをthisで継承させオーバーロードさせれば良いんでしょうか?

(2)プログレスバーのフォームを表示させたいだけなのですが、.ShowDialog()では怒られ、.Showでは即座にフォームが消えたりでどうにもなりません。スレッドが消えるまで表示させるにはどうしたらいいでしょう?

(3)フォーム側のプログレスバーのValueなり、変数なりをスレッド稼動中に更新させるにはどうしたらいいでしょうか?

(4)は、大して気にしていないのですが、これが致命的に足りない!とかいうのがあればご指導願います。

以上長々となりましたが、お暇な方お力を御貸しください

このQ&Aに関連する最新のQ&A

A 回答 (3件)

>Keisanメソッドが言わばMainのような形で、フォームやらその他のメソッドは常にKeisanメソッドの従としたいのでした。



フォームに貼り付いたコントロールには、プライマリスレッドからしかアクセスできないのですよ。だから、redfox63 さんのような回答になる訳です。
    • good
    • 0
この回答へのお礼

なるほど、コントロールにはそんな制約があったんですか。
初めて知りました。どおりでそんな感じの解説やサンプルコードが見つからなかった訳か、と恥ずかしい余りです。
ありがとうございました。

お礼日時:2008/09/02 21:05

この部分は スレッド作成するイベント側で記述します


Thread thread = new Thread(new ThreadStart((2)) );
thread.Start();

(2)はデリゲートを指定しますので 引数なしのデリゲート用関数を用意します
FormProgressのキャプション(タイトル)の変更は Textプロパティでできます

Public Class SumLoop
{
  public int nCnt = 0;
  public String sMsg = "";
  public void keisan()
  {
    FromProgress frm = new FormProgress();
    frm.Text = sMsg;
    frm.setProgrssMax( nCnt );
    frm.Show();

    for( int i = 0; i < nCnt; i++ ) {
      frm.setProgressValue( i );
      Thread.Sleep( 10 );
    }
  }
}

ProgessBarの最大値は Maximumプロパティを操作するので 外部から扱えるようにメソッドを追加しましょう

public void setProgressMax( int nMax )
{
  progressBar1.Maximum = nMax;
}

スレッド起動側のイベントで
SumLoop objSL = new SumLoop();
objSL.nCnt = 200;
objSL.sMsg = "タイトル";
Thread thread = new Thread( new ThreadStart( objSL.Keisan ) );
thread.Start();
といった具合でしょう
    • good
    • 1
この回答へのお礼

わざわざコードまで付けて頂いて恐縮です。
ただ、こちらの方法では計算(Keisanメソッド)をスレッド化するようです。
私のコードと質問内容の書き方が悪いといえばそれまでですが
Keisanメソッドが言わばMainのような形で、フォームやらその他のメソッドは常にKeisanメソッドの従としたいのでした。
後学の参考とさせて頂きます。

お礼日時:2008/09/02 20:08

こういうときには、BackgroundWorker という便利なものがありますので、そちらを使いましょう。



http://www.atmarkit.co.jp/fdotnet/dotnettips/436 …
http://msdn.microsoft.com/ja-jp/library/system.c …(VS.80).aspx
    • good
    • 0
この回答へのお礼

ご意見ありがとうございます、不思議なことにリンクが紫色でした。
ただ、今回教えて頂きたい事とはちょっと違うようです。

お礼日時:2008/09/02 19:58

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QC# 計算処理中に実行中ウィンドウを表示させたい。

アドバイスをお願いいたします。

やりたいこと:
(1)メインウィンドウで「計算始めるボタン」を押す。
(2)すると計算中には「実行中」の文字が別ウィンドウで立ち上がる。
(3)計算が終わると別ウィンドウが閉じる。

下記プログラムの不具合:
別ウィンドウで「実行中」の文字を出させたいが、文字部分が描画されない。

注意: 
下記プログラムはAthlon3000+で1秒ほどかかります。
CPUが遅いマシンで試す場合は「//計算処理」部分のfor重みを軽減させて実行して下さい。

using System;
using System.Drawing;
using System.Windows.Forms;

//メインウィンドウ
public class MainForm : Form {
private Button button;
private Label label;
public MainForm() {
button = new Button();
button.Text = "計算GO!!";
button.Click += new System.EventHandler(button_click);
label = new Label();
label.Location = new Point(50,50);
label.Text = "メインウィンドウ!";
Controls.Add(button);
Controls.Add(label);
Text = "MainForm";
BackColor = Color.Blue;
}

static void Main() {
Application.Run(new MainForm());
}

//計算GOボタンをクリックした時の処理
private void button_click(object sender, System.EventArgs e) {
double z;
SubForm Sub = new SubForm();

Sub.Show();

//計算処理
for(int i=0; i<=500000000; i++)
z = double.MaxValue * double.MinValue;

Sub.Close();

MessageBox.Show("計算終了");
}
}

//計算中を通知するウィンドウ
public class SubForm : Form {
private Label label;
public SubForm(){
label = new Label();
label.Text = "実行中!";
label.Location = new Point(50,50);
Text = "計算中通知ウィンドウ";
BackColor = Color.Red;
Controls.Add(label);
}
}

アドバイスをお願いいたします。

やりたいこと:
(1)メインウィンドウで「計算始めるボタン」を押す。
(2)すると計算中には「実行中」の文字が別ウィンドウで立ち上がる。
(3)計算が終わると別ウィンドウが閉じる。

下記プログラムの不具合:
別ウィンドウで「実行中」の文字を出させたいが、文字部分が描画されない。

注意: 
下記プログラムはAthlon3000+で1秒ほどかかります。
CPUが遅いマシンで試す場合は「//計算処理」部分のfor重みを軽減させて実行して下さい。

using System;
using S...続きを読む

Aベストアンサー

このような場合はマルチスレッドにするのが常套手段だと思います。

例えば、ボタン押した時にウインドウを作成表示し、計算スレッドを起動。計算スレッドの終了時にウインドウを閉じるのような動作にします。
逆に、Formの方を新規のスレッドにする手もありますが。

WIN32 API呼び出すより楽です。

[HOWTO] Visual C# .NET を使用してスレッドを作成する方法
http://support.microsoft.com/default.aspx?scid=kb;ja;815804

C#プログラミング入門 第7回:マルチスレッドプログラミング
http://www.stackasterisk.jp/tech/dotNet/csharp07_02.jsp

参考URL:http://www.stackasterisk.jp/tech/dotNet/csharp07_02.jsp

QC#にて別クラスの関数を使いたい

C#にて、別クラスの関数を使用する方法を教えてほしいです。

下記のような、構造体を受け取るメソッドを作りました。

*****************************
private struct MyPoint
{
public int x;
public int y;
}

private void proc1(MyPoint pt)
{
MessageBox.Show("座標:" ; pt.x + "," + pt.y + "実行結果");
}

private void button1_Click(object sender ,System.EventArgs e)
{

MyPoint pt;
pt.x = 10;
pt.y = 20;
proc(pt);
}
*****************************

別のフォームのクラスから、proc1を呼び出したいのですが、やり方がわかりません。
どうか、教えてください。

Aベストアンサー

同じ定義をしたとしても別の名前空間に書いた構造体は同一とはみなされません。

呼び出し先クラスでの構造体を private では無く、public で宣言して下さい。

呼び出し元では、

MyClass.MyPoint pt;

のようにして実体を作ります。

Qフルパスから最後のディレクトリ名を取得したい。

vb.netなのですが、例えば
c:\aaa\bbb\ccc\ddd\eee\fff.exe
というフルパスがあったとして、
eeeというディレクトリ名を取得したいのですが、
何か良い方法はないでしょうか。
それぞれのディレクトリ名の文字数や階層数は
決まっていないのですが、オススメの方法が
ありましたら、教えて頂けると助かります。

Aベストアンサー

MessageBox.Show(IO.Path.GetFileName(IO.Path.GetDirectoryName(myPath)))

IO.Path の GetDirectoryName でフォルダのフルパスを取得して、さらに IO.Path の GetFileName で最終フォルダ(またはファイル)の名前を取得。

QC# or VB プログレスバー

プログレスバーで進行状況を表示する処理を入れています。
http://dobon.net/vb/dotnet/programing/progressdialog.html

上記のサイトをパクってとりあえず作ってみました。きちんとできているのですが
1つだけ問題があって

try
{
ProgressDialog pd = new ProgressDialog();
//ダイアログのタイトルを設定
pd.Title = "カウントアップ";
//プログレスバーの最小値を設定
pd.Minimum = 0;
//プログレスバーの最大値を設定
pd.Maximum = 10;
//プログレスバーの初期値を設定
pd.Value = 0;

//進行状況ダイアログを表示する
pd.Show(this);

//処理を開始
for (int i = 1; i <= 10; i++)
{
//プログレスバーの値を変更する
pd.Value = i;
//メッセージを変更する
pd.Message = i.ToString() + "番目を処理中...";

//キャンセルされた時はループを抜ける
if (pd.Canceled)
break;

//1秒間待機する(本来なら何らかの処理を行う)
System.Threading.Thread.Sleep(1000);
}

//ダイアログを閉じる
pd.Close();
}
catch
{
MessageBox.Show("error");
}

こんな感じで使い、プログレスバー表示中に例外が走るとMessageBoxがモーダレスで
表示されてしまいます。プログレスバー表示前だとモーダルのままです。

色々調べたところ原因は裏でスレッドが走っているからだと思います。たぶん・・
ところが対処法となると少々困っています。モーダルでMessageBoxを表示させたいのですが
どうすればよいのでしょうか?教えてください。

プログレスバーで進行状況を表示する処理を入れています。
http://dobon.net/vb/dotnet/programing/progressdialog.html

上記のサイトをパクってとりあえず作ってみました。きちんとできているのですが
1つだけ問題があって

try
{
ProgressDialog pd = new ProgressDialog();
//ダイアログのタイトルを設定
pd.Title = "カウントアップ";
//プログレスバーの最小値を設定
pd.Minimum = 0;
//プログレスバーの最大値を設定
pd.Maximum = 10;
//プログレスバーの初期値を設定
pd.Value = 0;

//進行状況ダイア...続きを読む

Aベストアンサー

第一引数で親ウィンドウのオブジェクトを指定できるメソッドを使って
MessageBox.Show(this, "error");
とか。

Q【C#】 あるイベントから別イベントを呼び出す。

タイトルの通り、あるイベント内から別イベントの処理を呼び出したいと
考えています。ですが、方法がわかりません。

【質問投稿に至った経緯】
現状は、検索から一覧を表示し1つを選択、選択した内容の更新を行なうプログラムを作成しています。選択した内容を更新するところまではできました。ただ、更新内容を確認できるよう一覧画面に前回検索した内容を一覧表示させたいと考えています。この時、検索イベントを呼び出し、一覧を再表示させようと思っています。

Aベストアンサー

「検索イベント」とは、[検索]ボタンをクリックした時の
イベント処理の事でしょうか?
それならば、一覧表示処理を別ルーチンに分けて、[検索]
ボタンClickイベントと同じルーチンをCallする様にすれば
良いと思いますが?

Qc#でコマンドプロンプトを実行する方法

コマンドプロンプト上から音楽ファイルの変換が出来るffmpegを利用して
C#プログラムを作ろうと思い、下記のサイトを参考にしてc#プログラムを作りコマンドを入力してみたのですがうまくいきません。
しかし、同じコマンドをコマンドプロンプトを手動で開いて打ち込むと成功します。

参考にしたサイト:http://dobon.net/vb/dotnet/process/standardoutput.html
入力したコマンド:"E:/ffmpeg.exe" -i "E:/a.m4a" -b:a 320k "E:/a.mp3"
 ※コマンドの-b:a 320kの表記は320kbpsのビットレートで変換するコードです。
 ※a.m4aをa.mp3に320kbpsのビットレートで変換するコマンドになります。

現状をまとめると以下のようになります。
(1)コマンドプロンプトを手動で起動して、以下のコマンドを打ち込むとうまく変換してくれる。
"E:/ffmpeg.exe" -i "E:/a.m4a" -b:a 320k "E:/a.mp3"
(2)しかしこのコマンドを下記のコードで実行すると処理が行われない。
(3)そうなると下記のコード自体に問題があるように思われるが、
下記のコードで"dir c:\"など簡単なコマンドを実行すると成功する。

ダブルクオテーション(")やスペースなどに問題があるのかと思いいろいろと試してみましたがダメでした。
どうすれば下記のコードで"E:/ffmpeg.exe" -i "E:/a.m4a" -b:a 320k "E:/a.mp3"のようなコマンドを実行出来るのでしょうか?
実行する方法、もしくは違うコードで実行する方法などを知っておられる方、ぜひご教授ください!非常に困っております。


---------------------------------------------------------------------------------------------------
■コマンドプロンプトをC#上から実行するコード
http://dobon.net/vb/dotnet/process/standardoutput.htmlのコードの丸写し
---------------------------------------------------------------------------------------------------
//Processオブジェクトを作成
System.Diagnostics.Process p = new System.Diagnostics.Process();

//ComSpec(cmd.exe)のパスを取得して、FileNameプロパティに指定
p.StartInfo.FileName = System.Environment.GetEnvironmentVariable("ComSpec");
//出力を読み取れるようにする
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = false;
//ウィンドウを表示しないようにする
p.StartInfo.CreateNoWindow = true;
//コマンドラインを指定("/c"は実行後閉じるために必要)


//○成功する
p.StartInfo.Arguments = "dir c:\";
//×失敗する
p.StartInfo.Arguments = "\"E:/ffmpeg.exe\" -i \"E:/a.m4a\" -b:a 320k \"E:/a.mp3\";


//起動
p.Start();
//出力を読み取る
string results = p.StandardOutput.ReadToEnd();
//プロセス終了まで待機する
//WaitForExitはReadToEndの後である必要がある
//(親プロセス、子プロセスでブロック防止のため)
p.WaitForExit();
p.Close();

//出力された結果を表示
Console.WriteLine(results);
---------------------------------------------------------------------------------------------------

コマンドプロンプト上から音楽ファイルの変換が出来るffmpegを利用して
C#プログラムを作ろうと思い、下記のサイトを参考にしてc#プログラムを作りコマンドを入力してみたのですがうまくいきません。
しかし、同じコマンドをコマンドプロンプトを手動で開いて打ち込むと成功します。

参考にしたサイト:http://dobon.net/vb/dotnet/process/standardoutput.html
入力したコマンド:"E:/ffmpeg.exe" -i "E:/a.m4a" -b:a 320k "E:/a.mp3"
 ※コマンドの-b:a 320kの表記は320kbpsのビットレートで変換するコー...続きを読む

Aベストアンサー

>うまくいきません。

「なにが」「どう」「いまくいかない」んでしょうか?

プロセス起動した後に無反応になる?
プロセス終了した後に表示されるべきメッセージが表示されない?
プロセス起動できない?
起動したffmpeg.exeが終了しても戻ってこない?

参考ページではcmd.exeに/cオプションを指定しているようですが、
変更されたソースでは指定していないようで…。
その場合、
p.WaitForExit();
でちゃんと戻ってこれるんですかね?
# 起動したcmd.exe自体は終了していないはずですが…
# /Cも/Kも無かった場合ってどういう動作するんですかね?(Windows7 Pro 64Bitでcmd dirとしたら無視されてしまいましたが)

cmd.exe経由でなくても、必要条件満たせばffmpeg.exeの起動は可能と思いますよ。
ffmpeg.exeを利用するフロントエンドアプリなんかもそうしているでしょうし。
「ffmpeg.exe フロントエンド」で検索してみるとアプリは見つかるかと。

QDataGridViewで指定したセルの値を取得

こんにちは。

VB2008のDataGridViewで指定したセルの値を取得をする方法がわかりません。
どなたか教えてください。

Aベストアンサー

こんばんは.

 Dim Data As String
 Data = Me.DataGridView(0, 2).Value
 MsgBox(Data)

みたいな感じで取れないですかね???

QC# インスタンスの破棄

C#でインスタンスの破棄を明示的に行いたいのですが、
実際の開発現場では、どのように行っているのでしょうか?

自分で調べると「ガベージコレクタ」が暗黙的に行っているようですが明示的には行わないのが普通なのでしょうか?
もしくは、「Dispose」を使用して明示的に行うのが普通なのでしょうか?

実際に開発されている方からすると簡単な事かもしれませんが教えて頂けると助かります。

以上ですが、よろしくお願いいたします。

Aベストアンサー

結論から言うと、どちらでも良いです。
できれば生成から破棄まで考えて開発できると良いですね。

ガベージコレクションが実行されることで自動開放されますから、
一切.close()や.dispose()を使わなかったとしてもプログラムが
不正終了してしまう事はほとんどありません。

実際の開発では使わなくなったものを使わなくなった時点で
明示的に破棄することが多いです。正確には明示的に破棄するもの、
明示的に破棄しないもの、の2種類に分類しています。

例えばファイルを読み書きするストリーム系のオブジェクトや
データベースとのコネクションなどです。これは開発会社や
開発チーム、案件によって若干違っていて、徹底するところや
適当なところもあります。個人的には徹底したい派ですが。。。

ガベージコレクションが発生するとプログラムの実行動作が
遅くなり、また瞬間的に大きな負担がかかることがあります。
そのため全てをガベージコレクタに任せるのではなく、
明示的に開放できるもの、メモリを大量に消費するものは
その都度、適切に開放していくことで処理効率が良くなります。

プログラミング関連の調べ物で、サンプルソース等を見ることが
あるかと思います。この時サンプルで明示的に開放していたら、
それは明示的に開放したほうが良いもの、と思いましょう。
これだけでもステップアップになりますね。

結論から言うと、どちらでも良いです。
できれば生成から破棄まで考えて開発できると良いですね。

ガベージコレクションが実行されることで自動開放されますから、
一切.close()や.dispose()を使わなかったとしてもプログラムが
不正終了してしまう事はほとんどありません。

実際の開発では使わなくなったものを使わなくなった時点で
明示的に破棄することが多いです。正確には明示的に破棄するもの、
明示的に破棄しないもの、の2種類に分類しています。

例えばファイルを読み書きするストリーム...続きを読む

QC#で共有変数の定義をするには

C#で共有変数の定義をするには、どうしたらよいでしょうか。具体的には、起動パラメータで、任意の文字列(3~4バイト)を渡して、C#アプリケーションを、起動し、プログラムの任意の場所で、そのパラメータを参照したいと考えています。起動パラメータの受け取りは、できるのですが、そのパラメータを、プログラムのどこからも参照できる領域(ここの定義方法が不明)に格納するには、どうしたらよいでしょうか。(2重起動を許す前提です。実行時に1つの目のプログラムにはパラメータ"XYZ"を渡し、2つ目のプログラムを起動時にはパラメータ"ABCD"を渡し、その値により、プログラムの動作を制御したいと思っています)
Windows-xp visual-studio2008 C#でwindowsアプリケーションを作成しています。

Aベストアンサー

namespace test1
{
  static class Program
  {
    /// <summary>
    /// アプリケーションのメイン エントリ ポイントです。
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
      if (args.Length > 0)
      {
        strArg = args[0];
      }
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
      Application.Run(new Form1());
    }
    // ここに記述
    static public string strArg = null;
  }
}

メインクラスのメンバーとしてスコープが有効な場所に記述します

namespace test1
{
  static class Program
  {
    /// <summary>
    /// アプリケーションのメイン エントリ ポイントです。
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
      if (args.Length > 0)
      {
        strArg = args[0];
      }
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
      Application.Run(n...続きを読む

Q別のフォームで記述している関数を実行するには?C#

お世話になります。ド素人な質問ですみません。
C#なのですが例えばForm1で記述した関数(関数って呼ぶのかわかりませんが)をForm2で実行するにはどのようにしたらよいのでしょうか?
ネットで検索してみてもなかなかヒットしないのでこちらでお聞きします。

public partial class Form1 : Form
{
 public Form_OzzCalc()
 {
 InitializeComponent();
 }
 
 private void hoge()
 {
 ~
 }
}

このhoge()という関数を別のフォーム(例えばForm2)で呼び出して使うにはどのようにしたらよいのでしょうか?
privateをpublicに変更してもForm2ではこの関数を記述すると「'hoge'は現在のコンテキスト内に存在しません」と出ます。
何か参考になるサイトでも構いません。よろしくお願いいたします。

Aベストアンサー

この記述方法ですとForm1のインスタンス経由で関数を実行します

Form2側からですと

((Form1)Application.OpenForms["Form1"]).hoge();
といった具合です


下のように Form1クラスにスタティック(静的)関数を作成すれば
public static void foo()
{
}

Form2側からは
Form1.foo();
といった具合で実行できます

MessageBoxのShowがこの静的実装がされています


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング