ちなみにエラーは別のプロセスがそのファイルを使用しています。とかいう趣旨のもの。
エラーを拾って構造的な処理をしたいのではなくて、ただそのエラーが出るのが分かっているので無視して処理を進めたいということです。
936 :
デフォルトの名無しさん:02/12/11 23:23
現在、ListViewにデータを表示するアプリケーションを作成しています。
ListViewクラスはデータをListView内に保持するので、自作クラスにデータを持っていると
データの2重管理になってしまいます。
Model/Viewのような感じにしたいのですが、そういった考えは古いのでしょうか?
>>936 ListView以外にViewを持つ可能性があるなら、Model/Viewにして
データを二重持ちにしたほうがいいだろうねえ。
その可能性がないならListView派生クラスにボッコボッコ埋め込む。
>>935 try{}catch{}finally{}
catchしる。
>>937 どうもです。
リストビューで使うデータは他の表示でも使うので、どうしようかと。。
2重にするとデータの入れ替えとか起きたときに整合性を保つのが大変っぽい。
やっぱリストビューを表示とデータ管理クラス両方の役にするのがいいっぽいかな。
>>939 他のViewがあるなら、迷わず二重持ちにするけどなあ・・・
その、他のViewが参照のみで、操作をしないのであれば、
ListViewがデータ管理役になっても大丈夫かな?
>>938 特にしたい処理がなければfinallyだけで良いと思っていたんだけど。
空のcatchでやってみます。thanks
>>941 キャッチしないと例外が外に飛び出てっちゃうよ
>>942 try-finally だけの構文もありと書いてあったので、一番一般化されたエラー処理はこれなのかなと思っていました。
それはなんのためにあるの?
>>943 漏れはそのtry-finallyは使わないけど
メソッド使用してる側でcatchすれば用が足りる時、使えるかもね
でも
try{}catch(Exception error){ throw error;}finally{}
ってしたほうがわかりやすいと漏れは思ってる。あくまで漏れの考えだけどね・・・
946 :
デフォルトの名無しさん:02/12/12 04:45
>>939 迷わずModel/Viewにするのがいいんでは?
データは一元管理にしないといかんでしょ
そうしないと、いわれてるように更新、同期の管理など大変に.
ListViewだとどう実装するのかは知らないんですが、オーナードローになるのかな?
マスひとつひとつをセルとすると必要なセルの表示時にデータを見に行って表示って感じか
948 :
デフォルトの名無しさん:02/12/12 19:08
ほほう、C#でデリゲート以外のコールバックができるとな?
ここはC#のスレであって、C++のスレじゃないぞ。
ちなみに俺は解決した。
他にできる奴はいねーの?(藁
>>948 俺できるよ。でもそんなひれくれた聞き方するやつになんか教えない(藁
>>950 嘘つくな。お前にできるわけねーだろ。
本当だと言い張るんならソース見せてみろ。
>>951 嫌。出来ないと思われても良いよ。見せるよりマシ。
954 :
デフォルトの名無しさん:02/12/12 23:43
>956
立ってるよ
958 :
デフォルトの名無しさん:02/12/13 01:06
ほどよく荒れてるな(W
C言語で一定周期(100ms以内)の信号を画面に表示させたいのですが、
どの関数を使ったらよいかわかりません。どなたか教えていただけませんか?
961 :
デフォルトの名無しさん:02/12/13 04:18
>>960 いちおうこのスレはC#の質問なのでCの質問スレ捜して聞いてみたほうがいいよ。
それに質問も漠然としてるね。信号とはなんだろう。
C#、.Netで一定時間毎に何か処理させたいときはタイマーをフォームに貼り付けて、イベントハンドラを書くというのがやり方だけど。
unsafe コンテキストで
MyStruct s = new MyStruct( Hogehoge );
SomeNativeMethod( new IntPtr( &s ) );
// MyStruct preventOptimizing = s; // コメントはずすと正しく動くよ
ってな感じで、メソッドに渡すだけの構造体を使うと、
最適化で消滅して正しく動かなくなるんだよねぇ。
アドレス取ってるんだから最適化しても残さないといけないと思うんだけど。
だからpinしろって。
そういや、C#って、かなり積極的にガベコレしてるね。
965 :
デフォルトの名無しさん:02/12/13 08:54
デバッガでこまめにメモリ内容チェックしたから。
962はstructだからガベコレは無関係だぞ
968 :
デフォルトの名無しさん:02/12/13 12:30
structもガベコレされることすら知らない967がいるスレ
structがガベコレ対象だと思い込んでいる968が煽るスレ
structはガベコレされません。
>>962 これきついね。APIに渡すための構造体を wrap するクラスは全部 pin
するってこと。。。?
>>962 いや、それはstructの使い方が間違っているってことだろう。
アドレスをメソッドに渡したらアドレス(32ビット数値)が残っているだしょ。
IntPtrにキャストしてるんだから。
素直にヒープに取ればいいじゃん。ちなみにpinは関係ないよね。
>>971 いえ、実は構造体は Win32 の RECT で、メソッドは DirectX の LockRect なんですけどね。
このメソッドはその場で RECT を参照するだけなのでスタックに取っても大丈夫なはずなんです。
ちなみに preventOptimizing への代入を、メソッドを呼ぶ前に持ってきても正しく動きました。
IL 見てないので正確ではないかもしれませんが、アドレス演算子以外の何らかの形で一度も参照されないと変数自体が削除されるみたいなんです。
>>972 うー、そうですか。DirectXは全然わからないので、IL見せてください。
ちなみにこんなコードで実験してみましたが、結果はちゃんと3が返りました。これじゃ実験になってないですか?
-- DLL(cl dll2.cpp /LD)
extern "C" __declspec(dllexport) int WINAPI SomeNativeMethod(CONST RECT* ptr) {
RECT r;
CopyMemory(&r, ptr, sizeof(RECT));
return r.left + r.top;
}
-- Main(csc /unsafe /optimize+ /debug- Class1.cs)
class Class1 {
struct MyStruct {
internal int left;
internal int top;
internal int right;
internal int bottom;
internal MyStruct(int l, int t, int r, int b) {
left = l;
top = t;
right = r;
bottom = b;
}
}
[System.Runtime.InteropServices.DllImport("C:\\dll2.dll", EntryPoint="_SomeNativeMethod@4")]
unsafe static extern int SomeNativeMethod(IntPtr ptr);
つづき
[STAThread]
unsafe static void Main(string[] args) {
MyStruct s = new MyStruct(1,2,3,4);
int i =SomeNativeMethod( new IntPtr( &s ) );
Console.WriteLine(i);
// MyStruct preventOptimizing = s; // コメントはずすと正しく動くよ
}
}
まず、C#のソースコードです。
D3DLOCKED_RECT lockedRect = new D3DLOCKED_RECT();
RECT rect = Win32Methods.RectFromLTWH( 0, 0, size.Width, size.Height );
texture.GetSurfaceLevel( 0 ).LockRect( ref lockedRect, new IntPtr( &rect ), 0 );
//RECT preventOptimizing = rect;
/*
size にはテクスチャのサイズが入っています。
texture.GetSurfaceLevel( 0 ) で、テクスチャの最上位サーフェイスを取得して、
それをロック、ロックされた領域の情報(アドレスとピッチ)を D3DLOCKED_RECT に受け取ります。
*/
次に、正常に動く(preventOptimizing を使用している)コードの IL です。
// lockedRect
IL_020e: ldloca.s V_7 // ← lockedRect は V_7 に割り当てられる
IL_0210: initobj [Interop.DxVBLibA]DxVBLibA.D3DLOCKED_RECT
// rect = Win32Methods.RectFromLTWH(...)
IL_0216: ldc.i4.0
IL_0217: ldc.i4.0
IL_0218: ldloca.s V_0 // ← V_0 には size が入っている
IL_021a: call instance int32 [System.Drawing]System.Drawing.Size::get_Width()
IL_021f: ldloca.s V_0
IL_0221: call instance int32 [System.Drawing]System.Drawing.Size::get_Height()
IL_0226: call valuetype [Interop.DxVBLibA]DxVBLibA.RECT Win32Methods::RectFromLTWH(int32,
int32,
int32,
int32)
IL_022b: stloc.s V_8 // ← rect は V_8 に割り当てられる
// texture.GetSururfaceLevel( 0 )
IL_022d: ldsfld class [Interop.DxVBLibA]DxVBLibA.Direct3DTexture8 Sprites.CartoonMeshRenderer::texture
IL_0232: ldc.i4.0
IL_0233: callvirt instance class [Interop.DxVBLibA]DxVBLibA.Direct3DSurface8 [Interop.DxVBLibA]DxVBLibA.Direct3DTexture8::GetSurfaceLevel(int32)
// LockRect
IL_0238: ldloca.s V_7 // ← V_7 の lockedRect と
IL_023a: ldloca.s V_8 // ← V_8 の rect を渡した IntPtr と
IL_023c: newobj instance void [mscorlib]System.IntPtr::.ctor(void*)
IL_0241: ldc.i4.0 // ← 定数の 0 を使って LockRect を呼び出す
IL_0242: callvirt instance void [Interop.DxVBLibA]DxVBLibA.Direct3DSurface8::LockRect(valuetype [Interop.DxVBLibA]DxVBLibA.D3DLOCKED_RECT&,
native int,
int32)
ちなみに最後の preventOptimizing への代入は見事に消滅していました。
が、rect は無事 LockRect に渡されているので正しく動きます。
次に、preventOptimizing を使わずに、正しく動かないコードの IL です。
ほとんど同じですが。
// lockedRect
IL_020e: ldloca.s V_7
IL_0210: initobj [Interop.DxVBLibA]DxVBLibA.D3DLOCKED_RECT
// rect = Win32Methods.RectFromLTWH(...)
IL_0216: ldc.i4.0
IL_0217: ldc.i4.0
IL_0218: ldloca.s V_0
IL_021a: call instance int32 [System.Drawing]System.Drawing.Size::get_Width()
IL_021f: ldloca.s V_0
IL_0221: call instance int32 [System.Drawing]System.Drawing.Size::get_Height()
IL_0226: call valuetype [Interop.DxVBLibA]DxVBLibA.RECT Win32Methods::RectFromLTWH(int32,
int32,
int32,
int32)
IL_022b: pop // ←なぜか pop してしまう。 RECT は V_8 に割り当てられず綺麗さっぱり消滅します。
// texture.GetSururfaceLevel( 0 )
IL_022c: ldsfld class [Interop.DxVBLibA]DxVBLibA.Direct3DTexture8 Sprites.CartoonMeshRenderer::texture
IL_0231: ldc.i4.0
IL_0232: callvirt instance class [Interop.DxVBLibA]DxVBLibA.Direct3DSurface8 [Interop.DxVBLibA]DxVBLibA.Direct3DTexture8::GetSurfaceLevel(int32)
// LockRect
IL_0237: ldloca.s V_7
IL_0239: ldloca.s V_0 // ← なぜか size を渡す。
IL_023b: newobj instance void [mscorlib]System.IntPtr::.ctor(void*)
IL_0240: ldc.i4.0
IL_0241: callvirt instance void [Interop.DxVBLibA]DxVBLibA.Direct3DSurface8::LockRect(valuetype [Interop.DxVBLibA]DxVBLibA.D3DLOCKED_RECT&,
native int,
int32)
と言う感じで、rect が無くなって、指定してもいない size が渡されていました。
rect が無くなるのは最適化の影響ということで仕様としてもいいのですが、
その副作用で size が渡されるのは明らかにバグではないかと思うのですが。
# 下手するとセキュリティホールになり兼ねない気が...
ちなみに、この部分以外にも、構造体のアドレスを渡すところではだいたい再現してました。
うーん、Interop.DxVBLibA.dllも使って975のコードをコンパイルしてみたものの、
再現しませんでした。唯一書けなかったのはWin32Methods.RectFromLTWHなんですが、
これ何ですか?ILとしてもこの部分(の次)で妙なPOPが起きているようですが。。。
とりあえず自分でこんなのを作ったのですが、これを使って、無駄な代入をコメントアウトしても、
こちらでは正しいILのほうが生成されています。
class Win32Methods {
internal static RECT RectFromLTWH(int l, int t, int w, int h) {
RECT rect; rect.left = l;
rect.top = t; rect.right =w; rect.bottom = h;
return rect;
}
}
とりあえず再現する最小限のコードを乗っけます。(行数の関係でかなり押し込みましたが)
問答無用で最初のローカル変数が表示されるようです。
どうやら結構複雑な問題のようで、アドレスを取るだけでは問題は発生せず、
それより前に out パラメータを使ったメソッドを呼び出していると起こるようです。
それが必須条件なのかどうかはわかりませんが。
using System;
using System.Runtime.InteropServices;
public class Class1{
[STAThread] static void Main(string[] args){
int valueToShow = 1024; // なぜかこの値が表示される、数字は何でも良い
int preventOptimizing = valueToShow; // 最適化で消滅するのを防ぐ
// ↑この2行は無くてもかまわない、無い場合は
// ↓ の dummy が表示されるだけ、とにかく最初のローカル変数が表示される。
object dummy; // 型は object である必要はまったく無い、値型でも参照型でも
Dummy( out dummy ); // かまわないが、とにかく out パラメータで渡す。
unsafe{
int valueWantToShow = 1; // 表示されない
// int preventOptimizing2 = valueWantToShow; // しかしこの行を使えば正しく表示される。
ShowValue( new IntPtr( &valueWantToShow ) );
}
}
// 何でも良いがとにかく out で受け取る、代入しないとエラー出るのでとりあえず null をいれておく
// 代入する値は何でもかまわない。
static void Dummy( out object o ){ o = null; return; }
// ポインタの先の値を表示
static void ShowValue( IntPtr p ){
Console.WriteLine( "value = "+Marshal.ReadInt32( p ) );
}
}
>>981 うー、コピペして、.NET Framework 1.0 RTM、SP2、1.1 Final Betaで
試しましたが、いずれもValue=1でした。。。。
>>982 あれぇ〜〜??
ってことはもしかしてこっちの.NET Frameworkが古いのかも?
SP2当ててなかったっけな・・・?
ShowValue( new IntPtr( &valueWantToShow ) );
のところを
fixed(int* p = &valueWantToShow){
ShowValue(p);
}
にしたらどう?