相关疑难解决方法(0)

在for循环中分配委托的问题

我有一个能够插件(MEF)的应用程序.插件是导入服务的WPF UserControls.

用户可以从应用程序的主菜单中选择所需的插件.

为此,我使用以下循环:

foreach(IToolPlugin Plugin in ToolPlugins)
{
    Plugin.Init();
    MenuItem PluginMenuItem = Plugin.MenuItem; //New MenuItem but with Header set.
    PluginMenuItem.Click += new RoutedEventHandler(delegate(object o, RoutedEventArgs e) { DoSomething(Plugin.Control);});
    PluginsMenu.Items.add(PluginMenuItem);
}
Run Code Online (Sandbox Code Playgroud)

这对于单个项目非常好.但是,只要我有一个以上的插件,所有菜单项都会执行最后一个循环的委托.或者至少使用最后一个循环的Plugin.Control.

我怎样才能解决这个问题?
谢谢你的帮助.

c# delegates closures event-handling

6
推荐指数
1
解决办法
1213
查看次数

异步lambda中的参数

我试图同时运行几个任务,我遇到了一个似乎无法理解或解决的问题.

我以前有这样的功能:

private void async DoThings(int index, bool b) {
    await SomeAsynchronousTasks();
    var item = items[index];
    item.DoSomeProcessing();
    if(b)
        AVolatileList[index] = item; //volatile or not, it does not work
    else
        AnotherVolatileList[index] = item;
}
Run Code Online (Sandbox Code Playgroud)

我想用for循环调用Task.Run().但是我找不到向这个发送参数的方法,Action<int, bool>并且每个人都建议在类似的情况下使用lambdas:

for(int index = 0; index < MAX; index++) { //let's say that MAX equals 400 
    bool b = CheckSomething();
    Task.Run(async () => {
        await SomeAsynchronousTasks();
        var item = items[index]; //here, index is always evaluated at 400
        item.DoSomeProcessing();
        if(b)
            AVolatileList[index] …
Run Code Online (Sandbox Code Playgroud)

c# lambda asynchronous

6
推荐指数
1
解决办法
542
查看次数

如何将DataTable列的整个内容转换为C#中的分隔字符串?

我正在使用SqlDataAdapter和DataSet从MSSQL服务器检索数据.从那个DataSet我创建了一个DataTable.我的目标是将表的每一列转换为字符串,其中元素以逗号分隔.我想我会在分隔符工作之前先尝试字符串转换.

代码在ASP.Net页面的代码隐藏中运行.最终的目标是将字符串传递给jscript变量,这是一个"功能需求",我从列创建一个分隔的字符串,并且它必须最终作为jscript变量.

这是我到目前为止所拥有的:

    DataSet myDataSet = new DataSet();
    mySqlDataAdapter.Fill(myDataSet);
    DataTable temperature = myDataSet.Tables["Table"];

    // LOOP1
    foreach (DataRow row in temperature.Rows)
    // this loop works fine and outputs all elements
    // of the table to the web page, this is just to
    // test things out
    {
        foreach (DataColumn col in temperature.Columns)
        {
            Response.Write(row[col] + " ### ");
        }
        Response.Write("<br>");
    }

    // LOOP2
    foreach (DataColumn column in temperature.Columns)
    // this loop was meant to take all elements for each
    // column …
Run Code Online (Sandbox Code Playgroud)

c# asp.net datatable dataset datacolumn

5
推荐指数
1
解决办法
2万
查看次数

在foreach循环中使用谓词构建器的麻烦

我在foreach循环中构建谓词时遇到了麻烦.包含枚举器当前所在值的变量是我需要在谓词中放置的内容.

所以,

IQueryable query = getIQueryableSomehow();
Predicate = PredicateBuilder.False<SomeType>();
foreach (SomeOtherType t in inputEnumerable)
{
    Predicate = Predicate.Or( x => x.ListInSomeType.Contains(t) )
}
var results = query.Where(Predicate);
Run Code Online (Sandbox Code Playgroud)

我失败了.在Predicate中ORed一起使用的表达式基本上都是使用inputEnumerable中的相同t,当然我希望每个表达式ORed进入Predicate以使用与inputEnumerable不同的t.

我在循环之后查看调试器中的谓词,它看起来像IL.无论如何,那里的每个lambda看起来完全一样.

谁能告诉我这里可能做错了什么?

谢谢,

艾萨克

c# linq predicatebuilder

5
推荐指数
1
解决办法
865
查看次数

C#中的简单线程

可能重复:
C#捕获的变量循环

我正在研究几个简单的线程应用程序,但我似乎无法让它工作:

class ThreadTest
{
    static Queue<Thread> threadQueue = new Queue<Thread>();

    static void Main()
    {
        //Create and enqueue threads
        for (int x = 0; x < 2; x++)
        {
            threadQueue.Enqueue(new Thread(() => WriteNumber(x)));
        }

        while(threadQueue.Count != 0)
        {
            Thread temp = threadQueue.Dequeue();
            temp.Start();
        }

        Console.Read();
    }

    static void WriteNumber(int number)
    {
        for (int i = 0; i < 1000; i++)
        {
            Console.Write(number);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

目标基本上是逐个向队列添加线程,然后逐个遍历队列并弹出一个线程并执行它.因为我的for循环中有"x <2",它应该只生成两个线程 - 一个运行WriteNumber(0),另一个运行WriteNumber(1),这意味着我应该以1000 0和我的屏幕上的1000 1是不同的顺序,具体取决于线程的最终执行方式.

我最终得到的是2000 2.我提出的两个可能的解决方案是:我错过了一些明显的东西,或者将变量x发送到WriteNumber函数正在执行pass-by-reference而不是pass-by-value,所以当线程执行它们使用最新版本的x而不是设置函数时的版本.但是,据我所知,变量在C#中默认按值传递,如果在参数中包含"ref",则仅通过引用传递.

c# multithreading

5
推荐指数
2
解决办法
455
查看次数

循环中的Lambda变量捕获 - 这里发生了什么?

我想试试看,这里发生了什么?编译器生成什么样的代码?

public static void vc()
{
    var listActions = new List<Action>();

    foreach (int i in Enumerable.Range(1, 10))
    {
        listActions.Add(() => Console.WriteLine(i));
    }

    foreach (Action action in listActions)
    {
        action();
    }
}

static void Main(string[] args)
{ 
  vc();
}
Run Code Online (Sandbox Code Playgroud)

输出: 10 10 .. 10

根据这个,ActionHelper的新实例会为每次迭代创建.那么在这种情况下,我认为它应该打印1..10.有人能给我一些编译器在这里做的伪代码吗?

谢谢.

.net c# lambda

5
推荐指数
2
解决办法
3197
查看次数

即使所有事件都被触发,WaitOne()也会永远等待

假设螺纹形成4个单独的螺纹并等待它们中的每一个直到它们完成.每个线程都会休眠一段时间,只有当共享的Mutex opbject没有被另一个线程占用时才会终止,然后通过它完成的事件发出信号(这是我的代码的简化版本,但在同一个地方失败)

但是,大多数情况下主线程将在WaitOne()中的一个看似随机等待.

此外,我不得不将我的代码的某些部分注释掉,因为它导致了更多的意外行为(也就是说,在每个线程完成主线程之后会以某种方式跳回到for子句并导致IndexOutOfBounds)

class Threading
{
    static Mutex CM;
    static List<Manga> SharedList;
    static ManualResetEvent CEvent = new ManualResetEvent(false);
    static ManualResetEvent Event1 = new ManualResetEvent(false);
    static ManualResetEvent Event2 = new ManualResetEvent(false);
    static ManualResetEvent Event3 = new ManualResetEvent(false);
    static ManualResetEvent Event4 = new ManualResetEvent(false);

   public List<Manga> ThreadedMangaIndexCrawl(int MaxThreads)
   {
       CM = new Mutex(false);
       SharedList = new List<Manga>();

       ManualResetEvent[] evs = new ManualResetEvent[4];
       evs[0] = Event1;    // Event for t1
       evs[1] = Event2;    // Event for t2
       evs[2] = Event3;    // Event …
Run Code Online (Sandbox Code Playgroud)

c# multithreading waitone

5
推荐指数
1
解决办法
1310
查看次数

C#对象引用和Action类型

我有一个关于ActionC#中类型和Lambdas 的快速问题.这是代码:

    static void Main(string[] args)
    {
        List<Action> actions = new List<Action>();

        for (int I = 0; I < 10; I++)
            actions.Add(new Action(() => Print(I.ToString())));

        foreach (Action a in actions)
        {
            a.Invoke();
        }
        actions.Clear();

        int X;
        for (X = 0; X < 10; X++)
        {
            int V = X;
            actions.Add(new Action(() => Print(V.ToString())));
        }

        foreach (Action a in actions)
        {
            a.Invoke();
        }
        Console.ReadLine();
    }


    public static void Print(string s)
    {
        Console.WriteLine(s);
    }
Run Code Online (Sandbox Code Playgroud)

如果运行此代码,您将看到它连续十次输出10次,然后第二次输出数字0-9.它显然与我使用X vs I的方式有关,以及我如何在第二个循环中每次给我的动作一个新变量V ...可能每个新V都是内存中的新地址,但我是努力理解为什么I.ToString()在第一个循环中没有做同样的事情...为什么第一个Action中使用的I.ToString()与第二个例子的工作方式不一样?

c# lambda reference

5
推荐指数
1
解决办法
124
查看次数

为什么我的代理人只使用我的foreach循环中的最后一项?

场景:我正在构建一个调度系统和每个计时器事件,我想运行一个自定义方法而不是通常的Timer.Elapsed事件.

所以我写了这样的东西.

foreach (ScheduleElement schedule in schedules) {
    TimeSpan timeToRun = CalculateTime(schedule);
    schedule.Timer = new Timer(timeToRun.TotalMilliseconds);
    schedule.Timer.Elapsed += delegate { Refresh_Timer(schedule); };
    schedule.Timer.AutoReset = true;
    schedule.Timer.Enabled = true;
}
Run Code Online (Sandbox Code Playgroud)

确实如此简单,实际上确实创造了我的计时器.但是,我希望每个已发生的事件都使用它传入的schedule元素运行.我的问题是,为什么Elapsed事件只传递每个Timer.Elapsed事件的for循环中的最后一个ScheduleElement.

现在我知道是什么修复它,我只是不确定为什么.如果我回滚到原始的Timer.Elapsed事件并使用我自己的类扩展Timer类,我可以解决它.像这样.

修复:

foreach (ScheduleElement schedule in schedules) {
    TimeSpan timeToRun = CalculateTime(schedule);
    schedule.Timer = new TimerEx(timeToRun.TotalMilliseconds);
    schedule.Timer.Elapsed +=new System.Timers.ElapsedEventHandler(Refresh_Timer);
    schedule.Timer.Tag = schedule;
    schedule.Timer.AutoReset = true;
    schedule.Timer.Enabled = true;
}
Run Code Online (Sandbox Code Playgroud)

然后我把它object sender放回原来的物体,然后把它Tag从它上面剥下来,这给了我每个独特计时器的正确时间表.

再说一遍,为什么在所有Timers的foreach循环delegate { }中使用最后一个传递ScheduleElement

编辑1

Timer类

public TimerEx : …
Run Code Online (Sandbox Code Playgroud)

c# delegates timer

4
推荐指数
1
解决办法
683
查看次数

报告异步等待代码进度与进度条控件时使用 IProgress

private static async Task FuncAsync(DataTable dt, DataRow dr)
{
    try
    {
        await Task.Delay(3000); //assume this is an async http post request that takes 3 seconds to respond
        Thread.Sleep(1000) //assume this is some synchronous code that takes 2 second
    }
    catch (Exception e)
    {
        Thread.Sleep(1000); //assume this is synchronous code that takes 1 second
    }
}
Run Code Online (Sandbox Code Playgroud)
private async void Button1_Click(object sender, EventArgs e)
{
    List<Task> lstTasks = new List<Task>();

    DataTable dt = (DataTable)gridview1.DataSource;

    foreach (DataRow dr in dt.Rows)
    {
        lstTasks.Add(FuncAsync(dr["colname"].ToString());                
    } …
Run Code Online (Sandbox Code Playgroud)

c# multithreading asynchronous task-parallel-library async-await

4
推荐指数
1
解决办法
1万
查看次数