none
A property, indexer or dynamic member access may not be passed as an out or ref parameter RRS feed

  • 问题

  • 我用wpf写了个任务列表,类似于迅雷的任务列表,可以执行多个任务,每个任务列表包含文件名,进度条等等。任务列表每一行对应一个TaskInfo

    TaskInfo代码如下:

        public class TaskInfo : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
            public TaskInfo(string fp)
            {
                FileSystemInfo fsi= new DirectoryInfo(fp);
                FileName = fsi.Name;   
                FilePath = fp;     
                PbValue = 0;
    
            }
            //进度条值 
            private int pbvalue;
            public int PbValue
            {
                get { return pbvalue; }
                set
                {
                    pbvalue = value;
                    onPropertyChanged("PbValue");
                }
            }
            //文件名
            private string filename;
            public string FileName
            {
                get { return filename;}
                set
                {
                    filename = value;
                    onPropertyChanged("FileName");
                }
            }
            //文件路径
            private string filepath;
            public string FilePath
            {
                get { return filepath;}
                set
                {
                    filepath = value;
                    onPropertyChanged("FilePath");
                }
            }
    
            private void onPropertyChanged(string name)
            {
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(name));
                }
            }
        }

    列表中进度条的Value值绑定在PbValue上。

    由于在执行处理时是使用c语言的,所以用c语言封装成DLL供c#调用。

    c语言中主要函数为:

    void WaterErase(char * filepath, int * pbvalue)

    在c#中声明为

    public extern static void WaterErase(string filepath, ref int pbvalue)

    其中pbvalue表示进度条的值,我想通过引用来实时改变进度条的Value。

    具体调用我是这样做的,我写在一个Thread里面,代码如下:

        class TaskThread
        {
            private TaskInfo taskinfo = null;//任务信息
            private Thread thread;
            public TaskThread(TaskInfo _taskinfo)
            {
                taskinfo = _taskinfo;
            }
            private void run()
            {   //执行函数
                WaterErase(taskinfo.FilePath, ref taskinfo.PbValue);
    
            }       
            public void start()
            {
                if (thread == null)
                {
                    thread = new Thread(run);
                    thread.Start();
                }
            }
        }

    但是

     WaterErase(taskinfo.FilePath, ref taskinfo.PbValue);

    这代码出现问题

    A property, indexer or dynamic member access may not be passed as an out or ref parameter。

    这个问题怎么解决?



    2012年5月12日 3:04

答案

  • 异常信息说得很清楚了。属性、索引、动态类型的成员访问不能作为 ref 或者 out 参数。PbValue 在 TaskInfo 中是一个属性,ref TaskInfo.PbValue 其实并不能直接设置 private field pbValue 的值。因为属性只是语法唐,真正使用它的代码会变成 ref TaskInfo.get_PbValue()。

    您的问题是希望一个线程监听到另外一个非托管代码中某个返回值的变化。这会有很多方案。比如 MappedMemoryFile, WM_COPYDATA, SendMessage 等。个人认为 SendMessage 是比较靠谱的。简单的说基本思路就是非托管代码把要返回的值放到一个托管代码可以访问到的地方,然后托管代码利用 spin 或者 FileSystemWatcher 去轮询这个地方的值。相关具体实现可以自己搜索一下。


    Mark Zhou

    2012年5月17日 3:39

全部回复

  • Hi cloudending,

    欢迎来到C#论坛。

    你可以试试将

     WaterErase(taskinfo.FilePath, ref taskinfo.PbValue);

    改成:

    var temp=taskinfo.PbValue;
    WaterErase(taskinfo.FilePath, ref temp);
    taskinfo.PbValue=temp;

    祝你愉快。

    Bob Shen [MSFT]
    MSDN Community Support | Feedback to us

    2012年5月14日 7:01
    版主
  • 这样的话进度条值就不会动态变化了啊,直接跳到100....

    该怎么才能动态改进度条的值呢?

    dll中可以设置个全局变量之类的不?

    2012年5月14日 10:31
  • 异常信息说得很清楚了。属性、索引、动态类型的成员访问不能作为 ref 或者 out 参数。PbValue 在 TaskInfo 中是一个属性,ref TaskInfo.PbValue 其实并不能直接设置 private field pbValue 的值。因为属性只是语法唐,真正使用它的代码会变成 ref TaskInfo.get_PbValue()。

    您的问题是希望一个线程监听到另外一个非托管代码中某个返回值的变化。这会有很多方案。比如 MappedMemoryFile, WM_COPYDATA, SendMessage 等。个人认为 SendMessage 是比较靠谱的。简单的说基本思路就是非托管代码把要返回的值放到一个托管代码可以访问到的地方,然后托管代码利用 spin 或者 FileSystemWatcher 去轮询这个地方的值。相关具体实现可以自己搜索一下。


    Mark Zhou

    2012年5月17日 3:39
  • ok~感谢啦
    2012年5月18日 8:24