- PR -

ASP.NET C# で synchronized

投稿者投稿内容
ボルビ
ベテラン
会議室デビュー日: 2007/05/23
投稿数: 52
投稿日時: 2007-05-23 15:38
<環境>
Windows XP Professional SP2 , Visual Studio 2005 SP1, .NET Framework 2.0

index.aspxが実行された時に<img>タグに書かれているWebForm.aspxが呼ばれて
同時に処理が走った時にJavaでいうsynchronizedを使って一ファイルずつ
処理を実行させたいと考えています。

index.aspx
<img alt="t1" src="WebForm.aspx" />
<br />
<img alt="t2" src="WebForm.aspx" />

JavaでいうsynchronizedがC#ではlockを使えばできるとあったので、
下記のように試してみたのですが、デバッグでみると一回しか処理が
実行されていません。Javaと同じような動きにしたいのですがご教授お願い致します。

WebForm.aspx.cs(JFreeChart.NETでグラフを作成)
public partial class WebForm : System.Web.UI.Page {

protected void Page_Load(object sender, EventArgs e) {

lock (this)
{
String series1 = "我是1";
String series2 = "我是2";
String series3 = "我是3";

String category1 = "分類 1";
String category2 = "分類 2";
String category3 = "分類 3";
String category4 = "分類 4";
String category5 = "分類 5";
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(1.0, series1, category1);
dataset.addValue(4.0, series1, category2);
dataset.addValue(3.0, series1, category3);
dataset.addValue(5.0, series1, category4);
dataset.addValue(5.0, series1, category5);

dataset.addValue(5.0, series2, category1);
dataset.addValue(7.0, series2, category2);
dataset.addValue(6.0, series2, category3);
dataset.addValue(8.0, series2, category4);
dataset.addValue(4.0, series2, category5);

dataset.addValue(4.0, series3, category1);
dataset.addValue(3.0, series3, category2);
dataset.addValue(2.0, series3, category3);
dataset.addValue(3.0, series3, category4);
dataset.addValue(6.0, series3, category5);

JFreeChart chart = ChartFactory.createBarChart("Bar Chart 展示中心", "分類", "縦", dataset, PlotOrientation.VERTICAL, true, true, false);

chart.setBackgroundPaint(java.awt.Color.white);

CategoryPlot plot = chart.getCategoryPlot();
plot.setBackgroundPaint(java.awt.Color.lightGray);
plot.setDomainGridlinePaint(java.awt.Color.white);
plot.setDomainGridlinesVisible(true);
plot.setRangeGridlinePaint(java.awt.Color.white);

NumberAxis rangeAxis = (NumberAxis)plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

// disable bar outlines...
BarRenderer renderer = (BarRenderer)plot.getRenderer();
renderer.setDrawBarOutline(false);

// set up gradient paints for series...
GradientPaint gp0 = new GradientPaint(
0.0f, 0.0f, java.awt.Color.blue,
0.0f, 0.0f, new java.awt.Color(0, 0, 64)
);
GradientPaint gp1 = new GradientPaint(
0.0f, 0.0f, java.awt.Color.green,
0.0f, 0.0f, new java.awt.Color(0, 64, 0)
);
GradientPaint gp2 = new GradientPaint(
0.0f, 0.0f, java.awt.Color.red,
0.0f, 0.0f, new java.awt.Color(64, 0, 0)
);
renderer.setSeriesPaint(0, gp0);
renderer.setSeriesPaint(1, gp1);
renderer.setSeriesPaint(2, gp2);

Response.Clear();
Response.ContentType = "image/PNG";

ChartUtilities.writeChartAsPNG(Response.OutputStream, chart, 640, 480);

Response.Flush();
Response.End();
}

どっとねっとふぁん
ぬし
会議室デビュー日: 2005/02/23
投稿数: 935
投稿日時: 2007-05-23 16:13
> index.aspx
> <img alt="t1" src="WebForm.aspx" />
> <br />
> <img alt="t2" src="WebForm.aspx" />

この場合のt1とt2の処理はそもそも別のリクエストですから、処理も別のものとして走ります。
デバッグでどのように見ているかわかりませんが、それぞれのリクエストに対する処理は別のスレッドで走るのでその片方だけを見てるのではないでしょうか。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2007-05-23 16:19
引用:

ボルビさんの書き込み (2007-05-23 15:38) より:
index.aspx
<img alt="t1" src="WebForm.aspx" />
<br />
<img alt="t2" src="WebForm.aspx" />

JavaでいうsynchronizedがC#ではlockを使えばできるとあったので、
下記のように試してみたのですが、デバッグでみると一回しか処理が
実行されていません。Javaと同じような動きにしたいのですがご教授お願い致します。


たぶん、src が同じなので、ブラウザーが同じモノだと判断して、リクエストを1回しかおこなわないのでしょう。
ためしに、つぎのようにダミーの引数を付けてみてはどうでしょうか。

<img alt="t1" src="WebForm.aspx?a" />
<br />
<img alt="t2" src="WebForm.aspx?b" />

もしこれで挙動が違う(WebForm.aspx が2回動く)ようならば、言語仕様の問題ではなく、Web のキャッシュ等の問題に切り分けることができます。

--
unibon {B73D0144-CD2A-11DA-8E06-0050DA15BC86}
ボルビ
ベテラン
会議室デビュー日: 2007/05/23
投稿数: 52
投稿日時: 2007-05-23 16:38
引用:

どっとねっとふぁんさんの書き込み (2007-05-23 16:13) より:

この場合のt1とt2の処理はそもそも別のリクエストですから、処理も別のものとして走ります。
デバッグでどのように見ているかわかりませんが、それぞれのリクエストに対する処理は別のスレッドで走るのでその片方だけを見てるのではないでしょうか。




返信有難う御座います。

protected void Page_Load(object sender, EventArgs e) {

lock (this)
{
String series1 = "我是1"; ←ブレークポイント

上記の箇所にブレークポイント張ったんですが間違いでしょうか?
ここで2回止まると思ったんですが・・。
ボルビ
ベテラン
会議室デビュー日: 2007/05/23
投稿数: 52
投稿日時: 2007-05-23 17:05
引用:

unibonさんの書き込み (2007-05-23 16:19) より:

たぶん、src が同じなので、ブラウザーが同じモノだと判断して、リクエストを1回しかおこなわないのでしょう。
ためしに、つぎのようにダミーの引数を付けてみてはどうでしょうか。

<img alt="t1" src="WebForm.aspx?a" />
<br />
<img alt="t2" src="WebForm.aspx?b" />

もしこれで挙動が違う(WebForm.aspx が2回動く)ようならば、言語仕様の問題ではなく、Web のキャッシュ等の問題に切り分けることができます。

--
unibon {B73D0144-CD2A-11DA-8E06-0050DA15BC86}




返信有難う御座います。

引数をつけてみたら2回実行されました。
キャッシュの問題だとすると、引数を使わない場合は
<meta http-equiv="Pragma" CONTENT="no-cache">でいけるのかと
思ったんですがやっぱり無理でした。

こういった場合はダミー引数を設定しないと無理なんでしょうか?

囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2007-05-23 19:14
何故ロックする必要があるのでしょうか?
同じリクエストだから同じ結果を返すという事ですよね?
ブラウザの「同じモノだと判断して、リクエストを1回しかおこなわない」挙動で何が困るのでしょうか?

それと、提示されているコードでは this を lock していますが、これだとお望みの挙動は得られないでしょう。
Page クラス(この場合は WebForm.aspx )のインスタンスはリクエストの度に生成されるので、lock(this)の意味がありません。
_________________
囚人のジレンマな日々
ボルビ
ベテラン
会議室デビュー日: 2007/05/23
投稿数: 52
投稿日時: 2007-05-23 20:01
引用:

囚人さんの書き込み (2007-05-23 19:14) より:
何故ロックする必要があるのでしょうか?
同じリクエストだから同じ結果を返すという事ですよね?
ブラウザの「同じモノだと判断して、リクエストを1回しかおこなわない」挙動で何が困るのでしょうか?

それと、提示されているコードでは this を lock していますが、これだとお望みの挙動は得られないでしょう。
Page クラス(この場合は WebForm.aspx )のインスタンスはリクエストの度に生成されるので、lock(this)の意味がありません。




ファイルは一つだけど結果は複数で全て内容が違うグラフが表示されるということを
やりたかったんですが、まずはlockがsynchronizedと同じ動きができるかの確認した
かったので、説明が足りず申し訳ありませんでした。

なので、t1とt2は同じ結果ではないです。
<img alt="t1" src="WebForm.aspx" />
<br />
<img alt="t2" src="WebForm.aspx" />


引用:

それと、提示されているコードでは this を lock していますが、これだとお望みの挙動は得られないでしょう。
Page クラス(この場合は WebForm.aspx )のインスタンスはリクエストの度に生成されるので、lock(this)の意味がありません。



lockしてるようにも見えるんですがしてないんですね。
このような場合はどういうふうにするのが正しいのでしょうか?


囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2007-05-23 20:45
引用:

lockしてるようにも見えるんですがしてないんですね。
このような場合はどういうふうにするのが正しいのでしょうか?


全部のリクエストを排他処理したければ、以下のようなかんじです。
コード:
public partial class WebForm : System.Web.UI.Page {
	private static object syncObject = new object();
	
	protected void Page_Load(object sender, EventArgs e) {
		
		lock(syncObject) {
			// 排他処理したいコード
		}
	}
}



しかし、
引用:

ファイルは一つだけど結果は複数で全て内容が違うグラフが表示されるということを
やりたかったんですが、まずはlockがsynchronizedと同じ動きができるかの確認した
かったので、説明が足りず申し訳ありませんでした。


とあるので、ファイルへのアクセスを排他処理したいという意味ですか?
だったら、私の書いたコードも問題です。他のページで同じファイルにアクセスするなら意味を成しませんので。他のページでも同じオブジェクトのロックを取得する必要あります。

なので、シングルトンオブジェクト等を作り、それを lock するようにするか、ファイルにアクセスする処理をラップしたクラスを作り、そのクラスをスレッドセーフにするかした方がよいでしょう。

要は、lock するオブジェクトを何にするかを意識してください。
_________________
囚人のジレンマな日々

スキルアップ/キャリアアップ(JOB@IT)